implemented the sales and revenue report
This commit is contained in:
@@ -784,6 +784,65 @@ export async function getMasterCatalog(opts: {
|
||||
);
|
||||
}
|
||||
|
||||
export interface CreateProductLocationInput {
|
||||
tenantid: number;
|
||||
locationid: number;
|
||||
productid: number;
|
||||
qty: number;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
/** POST /products/createproductlocation — Add a product to a store catalogue / inventory. */
|
||||
export async function createProductLocation(input: CreateProductLocationInput): Promise<Row> {
|
||||
return fiestaSend<Row>('products/createproductlocation', 'POST', input);
|
||||
}
|
||||
|
||||
export interface StockRequestInput {
|
||||
tenantid: number;
|
||||
locationid: number;
|
||||
productid: number;
|
||||
qty: number;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
/** POST /products/createstockrequest — Store user requests stock. */
|
||||
export async function createStockRequest(input: StockRequestInput): Promise<Row> {
|
||||
return fiestaSend<Row>('products/createstockrequest', 'POST', input);
|
||||
}
|
||||
|
||||
/** /products/getstockrequests?tenantid=&locationid=&status=&pageno=&pagesize= —
|
||||
* Fetch pending/approved stock requests. */
|
||||
export async function getStockRequests(opts: {
|
||||
tenantid: number;
|
||||
locationid?: number;
|
||||
status?: string;
|
||||
pageno?: number;
|
||||
pagesize?: number;
|
||||
}): Promise<Row[]> {
|
||||
return toRows(
|
||||
await fiestaGet('products/getstockrequests', {
|
||||
tenantid: opts.tenantid,
|
||||
locationid: opts.locationid,
|
||||
status: opts.status ?? '',
|
||||
pageno: opts.pageno ?? 1,
|
||||
pagesize: opts.pagesize ?? 50,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export interface UpdateStockRequestInput {
|
||||
requestid?: number;
|
||||
tenantid?: number;
|
||||
locationid?: number;
|
||||
productid?: number;
|
||||
status: string;
|
||||
}
|
||||
|
||||
/** PUT /products/updatestockrequest — Admin approves or rejects a stock request. */
|
||||
export async function updateStockRequest(input: UpdateStockRequestInput): Promise<Row> {
|
||||
return fiestaSend<Row>('products/updatestockrequest', 'PUT', input);
|
||||
}
|
||||
|
||||
/** /products/getproductcategories — global product categories. */
|
||||
export async function getProductCategories(): Promise<Row[]> {
|
||||
return toRows(await fiestaGet('products/getproductcategories', {}));
|
||||
|
||||
@@ -61,6 +61,13 @@ import {
|
||||
CreateTenantLocationInput,
|
||||
updateTenantLocation,
|
||||
UpdateTenantLocationInput,
|
||||
createProductLocation,
|
||||
createStockRequest,
|
||||
getStockRequests,
|
||||
updateStockRequest,
|
||||
CreateProductLocationInput,
|
||||
StockRequestInput,
|
||||
UpdateStockRequestInput,
|
||||
} from './fiestaApi';
|
||||
|
||||
export const fiestaKeys = {
|
||||
@@ -97,6 +104,7 @@ export const fiestaKeys = {
|
||||
fleetSummary: (params: Record<string, unknown>) => ['fiesta', 'fleetSummary', params] as const,
|
||||
users: (params: Record<string, unknown>) => ['fiesta', 'users', params] as const,
|
||||
user: (userid: number) => ['fiesta', 'user', userid] as const,
|
||||
stockRequests: (params: Record<string, unknown>) => ['fiesta', 'stockRequests', params] as const,
|
||||
};
|
||||
|
||||
// ── Orders ──────────────────────────────────────────────────────────────────
|
||||
@@ -685,6 +693,52 @@ export function useFiestaProductSubcategories(opts: { categoryid: number; tenant
|
||||
});
|
||||
}
|
||||
|
||||
export function useFiestaGetStockRequests(opts: {
|
||||
tenantid: number;
|
||||
locationid?: number;
|
||||
status?: string;
|
||||
pageno?: number;
|
||||
pagesize?: number;
|
||||
}) {
|
||||
return useQuery({
|
||||
queryKey: fiestaKeys.stockRequests(opts),
|
||||
queryFn: () => getStockRequests(opts),
|
||||
enabled: Boolean(opts.tenantid),
|
||||
});
|
||||
}
|
||||
|
||||
export function useFiestaCreateProductLocation() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (input: CreateProductLocationInput) => createProductLocation(input),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['fiesta', 'productLocations'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useFiestaCreateStockRequest() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (input: StockRequestInput) => createStockRequest(input),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['fiesta', 'stockRequests'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useFiestaUpdateStockRequest() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (input: UpdateStockRequestInput) => updateStockRequest(input),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['fiesta', 'stockRequests'] });
|
||||
qc.invalidateQueries({ queryKey: ['fiesta', 'stockStatement'] });
|
||||
qc.invalidateQueries({ queryKey: ['fiesta', 'productStocks'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// ── Users ─────────────────────────────────────────────────────────────────────
|
||||
export function useFiestaUsers(opts: {
|
||||
tenantid: number;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { createProductLocation, FIESTA_TENANT_ID, FIESTA_PRIMARY_LOCATION_ID } from './fiestaApi';
|
||||
|
||||
export interface StoreCatalogueItem {
|
||||
productid: string;
|
||||
@@ -72,10 +73,28 @@ export function useStoreCatalogue() {
|
||||
|
||||
const has = (id: string) => items.some((i) => i.productid === id);
|
||||
const getQty = (id: string) => items.find((i) => i.productid === id)?.qty ?? 0;
|
||||
const add = (item: StoreCatalogueItem) => write([...read().filter((i) => i.productid !== item.productid), item]);
|
||||
const add = (item: StoreCatalogueItem) => {
|
||||
write([...read().filter((i) => i.productid !== item.productid), item]);
|
||||
createProductLocation({
|
||||
tenantid: FIESTA_TENANT_ID,
|
||||
locationid: FIESTA_PRIMARY_LOCATION_ID,
|
||||
productid: Number(item.productid),
|
||||
qty: item.qty,
|
||||
status: 'Active'
|
||||
}).catch(e => console.error('API createProductLocation failed:', e));
|
||||
};
|
||||
const remove = (id: string) => write(read().filter((i) => i.productid !== id));
|
||||
const setQty = (id: string, qty: number) =>
|
||||
write(read().map((i) => (i.productid === id ? { ...i, qty: Math.max(1, Math.round(qty) || 1) } : i)));
|
||||
const setQty = (id: string, qty: number) => {
|
||||
const safeQty = Math.max(1, Math.round(qty) || 1);
|
||||
write(read().map((i) => (i.productid === id ? { ...i, qty: safeQty } : i)));
|
||||
createProductLocation({
|
||||
tenantid: FIESTA_TENANT_ID,
|
||||
locationid: FIESTA_PRIMARY_LOCATION_ID,
|
||||
productid: Number(id),
|
||||
qty: safeQty,
|
||||
status: 'Active'
|
||||
}).catch(e => console.error('API updateProductLocation failed:', e));
|
||||
};
|
||||
|
||||
return { items, has, getQty, add, remove, setQty };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user