revert(web): eliminar feature de reserva de numero en UI ADM-008
Eliminar secuencias.api.ts, useReservarNumero.ts, SecuenciasPanel.tsx, TipoComprobante enum y tipos ReservarNumeroResponse/ProximoNumeroResponse. Quitar SecuenciasPanel del PuntoDeVentaDetailPage.
This commit is contained in:
@@ -1,22 +0,0 @@
|
|||||||
import { axiosClient } from '@/api/axiosClient'
|
|
||||||
import type { TipoComprobante, ReservarNumeroResponse, ProximoNumeroResponse } from '../types'
|
|
||||||
|
|
||||||
export async function reservarNumero(
|
|
||||||
puntoDeVentaId: number,
|
|
||||||
tipoComprobante: TipoComprobante,
|
|
||||||
): Promise<ReservarNumeroResponse> {
|
|
||||||
const response = await axiosClient.post<ReservarNumeroResponse>(
|
|
||||||
`/api/v1/admin/puntos-de-venta/${puntoDeVentaId}/secuencias/${tipoComprobante}/reservar`,
|
|
||||||
)
|
|
||||||
return response.data
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getProximoNumero(
|
|
||||||
puntoDeVentaId: number,
|
|
||||||
tipoComprobante: TipoComprobante,
|
|
||||||
): Promise<ProximoNumeroResponse> {
|
|
||||||
const response = await axiosClient.get<ProximoNumeroResponse>(
|
|
||||||
`/api/v1/admin/puntos-de-venta/${puntoDeVentaId}/secuencias/${tipoComprobante}/proximo`,
|
|
||||||
)
|
|
||||||
return response.data
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
import { toast } from 'sonner'
|
|
||||||
import { Button } from '@/components/ui/button'
|
|
||||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
|
|
||||||
import { TipoComprobante } from '../types'
|
|
||||||
import { useReservarNumero, useProximoNumero } from '../hooks/useReservarNumero'
|
|
||||||
|
|
||||||
const TIPOS: Array<{ value: TipoComprobante; label: string }> = [
|
|
||||||
{ value: TipoComprobante.FacturaA, label: 'Factura A' },
|
|
||||||
{ value: TipoComprobante.FacturaB, label: 'Factura B' },
|
|
||||||
{ value: TipoComprobante.FacturaC, label: 'Factura C' },
|
|
||||||
{ value: TipoComprobante.NotaCreditoA, label: 'Nota Crédito A' },
|
|
||||||
{ value: TipoComprobante.NotaCreditoB, label: 'Nota Crédito B' },
|
|
||||||
{ value: TipoComprobante.NotaCreditoC, label: 'Nota Crédito C' },
|
|
||||||
]
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
puntoDeVentaId: number
|
|
||||||
disabled: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export function SecuenciasPanel({ puntoDeVentaId, disabled }: Props) {
|
|
||||||
return (
|
|
||||||
<div className="rounded-md border border-border">
|
|
||||||
<div className="border-b border-border px-4 py-3">
|
|
||||||
<h2 className="text-sm font-semibold">Reserva de números de comprobante</h2>
|
|
||||||
<p className="text-xs text-muted-foreground">
|
|
||||||
Cada reserva incrementa el correlativo y devuelve el número asignado.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<Table>
|
|
||||||
<TableHeader>
|
|
||||||
<TableRow>
|
|
||||||
<TableHead>Tipo</TableHead>
|
|
||||||
<TableHead className="text-right">Próximo número</TableHead>
|
|
||||||
<TableHead className="text-right">Acción</TableHead>
|
|
||||||
</TableRow>
|
|
||||||
</TableHeader>
|
|
||||||
<TableBody>
|
|
||||||
{TIPOS.map((tipo) => (
|
|
||||||
<SecuenciaRow
|
|
||||||
key={tipo.value}
|
|
||||||
puntoDeVentaId={puntoDeVentaId}
|
|
||||||
tipoValue={tipo.value}
|
|
||||||
tipoLabel={tipo.label}
|
|
||||||
disabled={disabled}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
interface RowProps {
|
|
||||||
puntoDeVentaId: number
|
|
||||||
tipoValue: TipoComprobante
|
|
||||||
tipoLabel: string
|
|
||||||
disabled: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
function SecuenciaRow({ puntoDeVentaId, tipoValue, tipoLabel, disabled }: RowProps) {
|
|
||||||
const proximo = useProximoNumero(puntoDeVentaId, tipoValue)
|
|
||||||
const reservar = useReservarNumero(puntoDeVentaId)
|
|
||||||
|
|
||||||
const handleReservar = () => {
|
|
||||||
reservar.mutate(tipoValue, {
|
|
||||||
onSuccess: (data) => {
|
|
||||||
toast.success(`${tipoLabel}: número ${data.numeroReservado} reservado`)
|
|
||||||
},
|
|
||||||
onError: (err: unknown) => {
|
|
||||||
const apiError = err as { response?: { data?: { error?: string } } }
|
|
||||||
const code = apiError.response?.data?.error ?? 'error'
|
|
||||||
toast.error(`No se pudo reservar: ${code}`)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TableRow>
|
|
||||||
<TableCell>{tipoLabel}</TableCell>
|
|
||||||
<TableCell className="text-right font-mono">
|
|
||||||
{proximo.isLoading ? '…' : proximo.data?.proximoNumero ?? '—'}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className="text-right">
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="outline"
|
|
||||||
disabled={disabled || reservar.isPending}
|
|
||||||
onClick={handleReservar}
|
|
||||||
>
|
|
||||||
{reservar.isPending ? 'Reservando…' : 'Reservar'}
|
|
||||||
</Button>
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
|
||||||
import { reservarNumero, getProximoNumero } from '../api/secuencias.api'
|
|
||||||
import type { TipoComprobante } from '../types'
|
|
||||||
|
|
||||||
// ─── Reservar ────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
export function useReservarNumero(puntoDeVentaId: number) {
|
|
||||||
const queryClient = useQueryClient()
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: (tipoComprobante: TipoComprobante) =>
|
|
||||||
reservarNumero(puntoDeVentaId, tipoComprobante),
|
|
||||||
onSuccess: (_data, tipoComprobante) => {
|
|
||||||
// Invalidate the proximo query for this pdv+tipo so it refetches
|
|
||||||
queryClient.invalidateQueries({
|
|
||||||
queryKey: ['puntos-de-venta', 'proximo', puntoDeVentaId, tipoComprobante],
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ─── Próximo número (read-only) ──────────────────────────────────────────────
|
|
||||||
|
|
||||||
export function useProximoNumero(puntoDeVentaId: number, tipoComprobante: TipoComprobante) {
|
|
||||||
return useQuery({
|
|
||||||
queryKey: ['puntos-de-venta', 'proximo', puntoDeVentaId, tipoComprobante],
|
|
||||||
queryFn: () => getProximoNumero(puntoDeVentaId, tipoComprobante),
|
|
||||||
enabled: !!puntoDeVentaId,
|
|
||||||
staleTime: 5_000,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,6 @@ import { useMedio } from '../../medios/hooks/useMedio'
|
|||||||
import { DeactivatePuntoDeVentaModal } from '../components/DeactivatePuntoDeVentaModal'
|
import { DeactivatePuntoDeVentaModal } from '../components/DeactivatePuntoDeVentaModal'
|
||||||
import { MedioInactivoBanner } from '../components/MedioInactivoBanner'
|
import { MedioInactivoBanner } from '../components/MedioInactivoBanner'
|
||||||
import { PdvInactivoBanner } from '../components/PdvInactivoBanner'
|
import { PdvInactivoBanner } from '../components/PdvInactivoBanner'
|
||||||
import { SecuenciasPanel } from '../components/SecuenciasPanel'
|
|
||||||
|
|
||||||
function formatDate(iso: string | null): string {
|
function formatDate(iso: string | null): string {
|
||||||
if (!iso) return '—'
|
if (!iso) return '—'
|
||||||
@@ -105,12 +104,6 @@ export function PuntoDeVentaDetailPage() {
|
|||||||
</div>
|
</div>
|
||||||
</CanPerform>
|
</CanPerform>
|
||||||
|
|
||||||
<CanPerform permission="administracion:puntos_de_venta:gestionar">
|
|
||||||
<SecuenciasPanel
|
|
||||||
puntoDeVentaId={puntoDeVentaId}
|
|
||||||
disabled={pdvInactivo || medioInactivo}
|
|
||||||
/>
|
|
||||||
</CanPerform>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,7 @@
|
|||||||
// ADM-008 — shared types for puntos-de-venta feature
|
// ADM-008 — shared types for puntos-de-venta feature
|
||||||
|
// NOTE: numeración AFIP (NumeroFactura, CAI) es asignada externamente por IMAC/Infogestión.
|
||||||
export enum TipoComprobante {
|
// Un worker futuro (INT-001) polleará la vista de Infogestión para asociar
|
||||||
FacturaA = 1,
|
// NumeroOrdenInterno ↔ NumeroFacturaAFIP + CAI. No se generan números aquí.
|
||||||
FacturaB = 2,
|
|
||||||
FacturaC = 3,
|
|
||||||
NotaCreditoA = 4,
|
|
||||||
NotaCreditoB = 5,
|
|
||||||
NotaCreditoC = 6,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PuntoDeVentaListItem {
|
export interface PuntoDeVentaListItem {
|
||||||
id: number
|
id: number
|
||||||
@@ -53,16 +47,6 @@ export interface PuntosDeVentaQuery {
|
|||||||
activo?: boolean
|
activo?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ReservarNumeroResponse {
|
|
||||||
tipoComprobante: TipoComprobante
|
|
||||||
numeroReservado: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ProximoNumeroResponse {
|
|
||||||
tipoComprobante: TipoComprobante
|
|
||||||
proximoNumero: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PagedResult<T> {
|
export interface PagedResult<T> {
|
||||||
items: T[]
|
items: T[]
|
||||||
page: number
|
page: number
|
||||||
|
|||||||
Reference in New Issue
Block a user