30 lines
3.8 KiB
React
30 lines
3.8 KiB
React
import React,{useEffect,useState} from 'react';
|
||
import {milliQuantity} from './StockReadWorkspace.jsx';
|
||
import {requestStockPeriod} from './stock-period-request.js';
|
||
|
||
export function StockPeriodTable({rows}) {
|
||
return <div className="table-wrap"><table><thead><tr><th>Artigo / unidade</th><th>Armazém</th><th>Abertura</th><th>Entradas</th><th>Saídas</th><th>Fecho</th><th>Movimentos no período</th></tr></thead>
|
||
<tbody>{rows.map(row=><tr key={`${row.stock_item_id}:${row.warehouse_id}`}><td>{row.code} · {row.name} · {row.unit}</td><td>{row.warehouse_code} · {row.warehouse_name}</td>
|
||
{['opening_milli','incoming_milli','outgoing_milli','closing_milli'].map(key=><td key={key}>{milliQuantity(row[key])}</td>)}<td>{row.period_movements}</td></tr>)}</tbody></table></div>;
|
||
}
|
||
export default function StockPeriodReportWorkspace({api,context}) {
|
||
const [query,setQuery]=useState(null),[data,setData]=useState(null),[error,setError]=useState(''),[loading,setLoading]=useState(false);
|
||
useEffect(()=>{if(!query)return;return requestStockPeriod({query,api,data:setData,error:setError,loading:setLoading});},[query,context.token]);
|
||
const submit=e=>{e.preventDefault();const values=Object.fromEntries(new FormData(e.currentTarget));setData(null);setQuery({view:'period',from:values.from,to:values.to,search:values.search,warehouse_id:values.warehouse_id||undefined,per_page:Number(values.per_page),page:1});};
|
||
return <section aria-label="Relatório físico por período"><h3>Resumo físico por artigo e armazém</h3>
|
||
<p>Escolha as datas do registo em UTC. Abertura antes do primeiro dia; fecho até ao fim do último dia. As designações são as actuais.</p>
|
||
<form onSubmit={submit}><label>Primeiro dia (UTC)<input name="from" type="date" min="1900-01-01" max="9998-12-31" required/></label><label>Último dia (UTC)<input name="to" type="date" min="1900-01-01" max="9998-12-31" required/></label>
|
||
<label>Artigo por código ou nome<input name="search" maxLength={100}/></label><label>Identificador do armazém autorizado<input name="warehouse_id" type="number" min="1"/></label>
|
||
<label>Linhas por página<select name="per_page" defaultValue="25"><option value="25">25</option><option value="100">100</option></select></label><button disabled={loading}>Consultar período</button></form>
|
||
{!query&&<p>Seleccione o período; não foi consultada nem escolhida uma data automaticamente.</p>}
|
||
{loading&&<p role="status">A consultar o período autorizado…</p>}
|
||
{error&&<div role="alert"><p>{error}</p><button onClick={()=>{setData(null);setQuery({...query,page:1,snapshot:undefined});}}>Actualizar relatório</button></div>}
|
||
{data&&<><p role="status">{data.notice}</p><p>{data.period.from} a {data.period.to} · {data.period.timezone} · referência {data.observed_at}. Página {data.pagination.page} de {data.pagination.last_page}; {data.pagination.total} pares artigo/armazém.</p>
|
||
<StockPeriodTable rows={data.rows}/>{data.rows.length===0&&<p>Sem pares com história elegível até ao fecho para estes filtros. Não se inventam existências zero.</p>}
|
||
<button disabled={loading||data.pagination.page<=1} onClick={()=>setQuery({...query,page:data.pagination.page-1,snapshot:data.snapshot})}>Anterior</button>
|
||
<button disabled={loading||data.pagination.page>=data.pagination.last_page} onClick={()=>setQuery({...query,page:data.pagination.page+1,snapshot:data.snapshot})}>Seguinte</button>
|
||
<button disabled={loading} onClick={()=>{setData(null);setQuery({...query,page:1,snapshot:undefined});}}>Nova referência de leitura</button></>}
|
||
<p>Fecho = abertura + entradas − saídas, por linha e unidade. Sem valorização, reservas, bloqueios ou disponibilidade calculada.</p>
|
||
</section>;
|
||
}
|