Add ticket management API and update baud rate handling
Introduces a new TicketsController and Ticket model to support ticket CRUD operations via new /api/ticket routes. Updates line_connection service to improve baud rate command sequence. Adjusts CardLine component to include stationId when emitting set_baud events. Minor improvements to socket_io_provider for safer disconnect handling.
This commit is contained in:
parent
c2d68c685c
commit
cbc4a8c9b0
|
|
@ -0,0 +1,188 @@
|
|||
import Ticket from '#models/ticket'
|
||||
import type { HttpContext } from '@adonisjs/core/http'
|
||||
import db from '@adonisjs/lucid/services/db'
|
||||
|
||||
export default class TicketsController {
|
||||
/**
|
||||
* List all tickets
|
||||
*/
|
||||
async get({ request, response, auth }: HttpContext) {
|
||||
try {
|
||||
const perPage = request.input('per_page', 1)
|
||||
const page = request.input('page', 1)
|
||||
|
||||
const queryLatest = Ticket.query()
|
||||
.where('station_id', request.input('station_id'))
|
||||
.where('sn', request.input('sn'))
|
||||
|
||||
const query = Ticket.query()
|
||||
.where('station_id', request.input('station_id'))
|
||||
.where('sn', request.input('sn'))
|
||||
.whereNot('status', 'closed')
|
||||
|
||||
const tickets = await query.orderBy('tickets.created_at', 'desc').paginate(page, perPage)
|
||||
return response.ok({
|
||||
status: true,
|
||||
data: tickets,
|
||||
latest:
|
||||
(await queryLatest.orderBy('tickets.created_at', 'desc').paginate(page, perPage)) || null,
|
||||
})
|
||||
} catch (error) {
|
||||
return response.internalServerError({
|
||||
status: false,
|
||||
message: 'Failed to fetch tickets',
|
||||
error,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async getAll({ request, response, auth }: HttpContext) {
|
||||
try {
|
||||
const perPage = request.input('per_page', 20)
|
||||
const page = request.input('page', 1)
|
||||
|
||||
const query = Ticket.query()
|
||||
.where('station_id', request.input('station_id'))
|
||||
.where('sn', request.input('sn'))
|
||||
// .whereNot('status', 'closed')
|
||||
|
||||
const tickets = await query.orderBy('tickets.created_at', 'desc').paginate(page, perPage)
|
||||
return response.ok({
|
||||
status: true,
|
||||
data: tickets,
|
||||
})
|
||||
} catch (error) {
|
||||
return response.internalServerError({
|
||||
status: false,
|
||||
message: 'Failed to fetch tickets',
|
||||
error,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ticket
|
||||
*/
|
||||
async create({ request, response, auth }: HttpContext) {
|
||||
try {
|
||||
const payload = await request.all()
|
||||
|
||||
const history = [
|
||||
{
|
||||
userId: payload.userId,
|
||||
userName: payload.userName,
|
||||
status: payload.status,
|
||||
description: payload.description.trim(),
|
||||
time: Date.now(),
|
||||
},
|
||||
]
|
||||
|
||||
const trx = await db.transaction()
|
||||
try {
|
||||
const ticket = await Ticket.create(
|
||||
{
|
||||
description: payload.description.trim(),
|
||||
model: payload.model.trim(),
|
||||
sn: payload.sn.trim(),
|
||||
stationId: payload.station_id,
|
||||
status: 'open',
|
||||
history: JSON.stringify(history),
|
||||
},
|
||||
{ client: trx }
|
||||
)
|
||||
|
||||
await trx.commit()
|
||||
|
||||
return response.ok({
|
||||
status: true,
|
||||
message: 'Ticket created successfully',
|
||||
data: ticket,
|
||||
})
|
||||
} catch (error) {
|
||||
await trx.rollback()
|
||||
|
||||
return response.internalServerError({
|
||||
status: false,
|
||||
message: 'Failed to create ticket, please try again!',
|
||||
error,
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
return response.internalServerError({
|
||||
status: false,
|
||||
message: 'Failed to create ticket',
|
||||
error,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single ticket by ID
|
||||
*/
|
||||
async show({ params, response }: HttpContext) {
|
||||
try {
|
||||
const ticket = await Ticket.findOrFail(params.id)
|
||||
return response.ok({ status: true, data: ticket })
|
||||
} catch (error) {
|
||||
return response.notFound({ status: false, message: 'Ticket not found' })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a ticket
|
||||
*/
|
||||
async update({ request, response, auth }: HttpContext) {
|
||||
try {
|
||||
const ticketId = request.param('id')
|
||||
const payload = await request.all()
|
||||
const ticket = await Ticket.findOrFail(ticketId)
|
||||
const history = {
|
||||
userId: payload.userId,
|
||||
userName: payload.userName,
|
||||
status: payload.status,
|
||||
description: payload.description.trim(),
|
||||
time: Date.now(),
|
||||
}
|
||||
if (!ticket) {
|
||||
return response.notFound({ message: 'Ticket not found' })
|
||||
}
|
||||
const listHistory = ticket.history ? JSON.parse(ticket.history) : []
|
||||
listHistory.unshift(history)
|
||||
payload.history = JSON.stringify(listHistory)
|
||||
ticket.merge(payload)
|
||||
await ticket.save()
|
||||
|
||||
return response.ok({ status: true, message: 'Ticket updated successfully', data: ticket })
|
||||
} catch (error) {
|
||||
return response.internalServerError({
|
||||
status: false,
|
||||
message: 'Failed to update ticket',
|
||||
error,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a ticket
|
||||
*/
|
||||
async delete({ request, response }: HttpContext) {
|
||||
try {
|
||||
const ticketId = request.param('id')
|
||||
const ticket = await Ticket.findOrFail(ticketId)
|
||||
|
||||
if (!ticket) {
|
||||
return response.notFound({ message: 'Ticket not found' })
|
||||
}
|
||||
|
||||
await ticket.delete()
|
||||
|
||||
return response.ok({ status: true, message: 'Ticket deleted successfully' })
|
||||
} catch (error) {
|
||||
return response.internalServerError({
|
||||
status: false,
|
||||
message: 'Failed to delete ticket',
|
||||
error,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import Station from '#models/station'
|
||||
import { BaseModel, belongsTo, column } from '@adonisjs/lucid/orm'
|
||||
import type { BelongsTo } from '@adonisjs/lucid/types/relations'
|
||||
import { DateTime } from 'luxon'
|
||||
import Line from './line.js'
|
||||
|
||||
export default class Ticket extends BaseModel {
|
||||
@column({ isPrimary: true })
|
||||
declare id: number
|
||||
|
||||
@column()
|
||||
declare description: string
|
||||
|
||||
@column()
|
||||
declare model: string
|
||||
|
||||
@column()
|
||||
declare sn: string
|
||||
|
||||
@column()
|
||||
declare stationId: string
|
||||
|
||||
@column()
|
||||
declare lineId: string
|
||||
|
||||
@column()
|
||||
declare status: string
|
||||
|
||||
@column()
|
||||
declare history: string
|
||||
|
||||
@belongsTo(() => Station, {
|
||||
foreignKey: 'station_id',
|
||||
})
|
||||
declare station: BelongsTo<typeof Station>
|
||||
|
||||
@belongsTo(() => Line, {
|
||||
foreignKey: 'line_id',
|
||||
})
|
||||
declare line: BelongsTo<typeof Line>
|
||||
|
||||
@column.dateTime({ autoCreate: true })
|
||||
declare createdAt: DateTime
|
||||
|
||||
@column.dateTime({ autoCreate: true, autoUpdate: true })
|
||||
declare updatedAt: DateTime
|
||||
}
|
||||
|
|
@ -192,13 +192,13 @@ export default class LineConnection {
|
|||
async writeCommand(cmd: string | Buffer<ArrayBuffer>, userName = '') {
|
||||
if (this.client.destroyed) {
|
||||
console.log(`⚠️ Cannot send, line ${this.config.lineNumber} is closed`)
|
||||
if (this.retryConnect <= 3) {
|
||||
await sleep(2000)
|
||||
console.log('Retry connect times', this.retryConnect)
|
||||
this.retryConnect += 1
|
||||
await this.connect()
|
||||
await this.writeCommand(cmd)
|
||||
}
|
||||
// if (this.retryConnect <= 3) {
|
||||
// await sleep(2000)
|
||||
// console.log('Retry connect times', this.retryConnect)
|
||||
// this.retryConnect += 1
|
||||
// await this.connect()
|
||||
// await this.writeCommand(cmd)
|
||||
// }
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -553,9 +553,11 @@ export default class LineConnection {
|
|||
async setBaud(baud: number) {
|
||||
this.writeCommand('enable\r\n')
|
||||
await sleep(500)
|
||||
this.writeCommand('configure terminal\r\n')
|
||||
await sleep(500)
|
||||
this.writeCommand('line console 0\r\n')
|
||||
await sleep(500)
|
||||
this.writeCommand(`speed ${baud}\r\n`)
|
||||
this.writeCommand(`speed ${baud.toString()}\r\n`)
|
||||
await sleep(500)
|
||||
this.writeCommand('end\r\n')
|
||||
await sleep(500)
|
||||
|
|
|
|||
|
|
@ -520,7 +520,7 @@ export class WebSocketIo {
|
|||
delete this.intervalMap[`${lineId}`]
|
||||
}
|
||||
const interval = setInterval(() => {
|
||||
lineConn.disconnect()
|
||||
if (lineConn.disconnect) lineConn.disconnect()
|
||||
// this.lineMap.delete(lineId)
|
||||
if (this.intervalMap[`${lineId}`]) {
|
||||
clearInterval(this.intervalMap[`${lineId}`])
|
||||
|
|
@ -544,7 +544,7 @@ export class WebSocketIo {
|
|||
for (const lineId of lineIds) {
|
||||
try {
|
||||
const line = this.lineMap.get(lineId)
|
||||
|
||||
// console.log(line?.config)
|
||||
if (line && line.config.status === 'connected') {
|
||||
this.lineConnecting = this.lineConnecting.filter((el) => el !== lineId)
|
||||
this.setTimeoutConnect(lineId, line, options.timeout)
|
||||
|
|
|
|||
|
|
@ -70,3 +70,14 @@ router
|
|||
router.post('/register', '#controllers/auth_controller.register')
|
||||
})
|
||||
.prefix('api/auth')
|
||||
|
||||
router
|
||||
.group(() => {
|
||||
router.post('/', '#controllers/tickets_controller.get')
|
||||
router.post('/all', '#controllers/tickets_controller.getAll')
|
||||
router.post('create', '#controllers/tickets_controller.create')
|
||||
|
||||
router.put('update/:id', '#controllers/tickets_controller.update')
|
||||
router.delete('delete/:id', '#controllers/tickets_controller.delete')
|
||||
})
|
||||
.prefix('api/ticket')
|
||||
|
|
|
|||
|
|
@ -408,6 +408,7 @@ const CardLine = ({
|
|||
socket?.emit("set_baud", {
|
||||
lineId: line.id,
|
||||
baud: el,
|
||||
stationId: Number(stationItem.id),
|
||||
});
|
||||
setIsDisabled(true);
|
||||
setTimeout(() => {
|
||||
|
|
@ -427,6 +428,7 @@ const CardLine = ({
|
|||
socket?.emit("set_baud", {
|
||||
lineId: line.id,
|
||||
baud: Number(valueBaud),
|
||||
stationId: Number(stationItem.id),
|
||||
});
|
||||
setValueBaud("");
|
||||
setIsDisabled(true);
|
||||
|
|
|
|||
Loading…
Reference in New Issue