import product catalogue

This commit is contained in:
2026-07-16 17:05:06 +05:30
parent 8a1527cef8
commit 11baf732b7
35 changed files with 2722 additions and 1513 deletions

View File

@@ -20,11 +20,11 @@
const FIESTA_BASE = import.meta.env.VITE_FIESTA_URL || 'https://fiesta.nearle.app/live/api/v1/web';
const FIESTA_MOB_BASE = import.meta.env.VITE_FIESTA_MOB_URL || 'https://fiesta.nearle.app/live/api/v1/mob';
/** Tenant / location scope shared by the merchant console (Ragul Stores, Coimbatore). */
export const FIESTA_TENANT_ID = 1087;
/** Tenant / location scope shared by the merchant console. */
export const FIESTA_TENANT_ID = 1135;
export const FIESTA_APPLOCATION_ID = 1;
/** Primary outlet for this tenant — the one carrying live orders/stock. */
export const FIESTA_PRIMARY_LOCATION_ID = 1097;
export const FIESTA_PRIMARY_LOCATION_ID = 1170;
export type Row = Record<string, unknown>;
type QueryParams = Record<string, string | number | undefined | null>;
@@ -167,7 +167,13 @@ export async function getOrderSummary(
todate: string,
locationid?: number,
): Promise<FiestaOrderSummary | null> {
const row = firstRow<Row>(await fiestaGet('orders/getordersummary', { tenantid, locationid, fromdate, todate }));
const row = firstRow<Row>(await fiestaGet('orders/getordersummary', {
tenantid,
locationid,
applocationid: locationid, // send both to bypass backend bugs
fromdate,
todate
}));
if (!row) return null;
return {
total: num(row.total),
@@ -192,9 +198,9 @@ export interface FiestaLocationSummary {
cancelled: number;
}
/** /orders/getlocationsummary?tenantid= — per-outlet order rollup. */
export async function getLocationSummary(tenantid: number): Promise<FiestaLocationSummary[]> {
return toRows<Row>(await fiestaGet('orders/getlocationsummary', { tenantid })).map((r) => ({
/** /orders/getlocationsummary?tenantid=&fromdate=&todate= — per-outlet order rollup. */
export async function getLocationSummary(tenantid: number, fromdate?: string, todate?: string): Promise<FiestaLocationSummary[]> {
return toRows<Row>(await fiestaGet('orders/getlocationsummary', { tenantid, fromdate, todate })).map((r) => ({
locationid: num(r.locationid),
locationname: str(r.locationname),
total: num(r.total),
@@ -622,9 +628,11 @@ export function cleanTenantLocations(rows: Row[]): Row[] {
});
}
/** /tenants/gettenantlocations?tenantid= — outlet locations for a tenant (test rows stripped). */
export async function getTenantLocations(tenantid: number): Promise<Row[]> {
return cleanTenantLocations(toRows(await fiestaGet('tenants/gettenantlocations', { tenantid })));
/** /tenants/gettenantlocations?tenantid=&userid= — outlet locations for a tenant (test rows stripped). */
export async function getTenantLocations(tenantid: number, userid?: number): Promise<Row[]> {
const params: Record<string, any> = { tenantid };
if (userid) params.userid = userid;
return cleanTenantLocations(toRows(await fiestaGet('tenants/gettenantlocations', params)));
}
/** /tenants/getalltenants?applocationid=&status=&pageno=&pagesize= — active tenants. */
@@ -737,7 +745,7 @@ export async function getProductStocks(opts: {
);
}
/** /products/getproductlocations?tenantid=&locationid=&subcategoryid=&pageno=&pagesize= —
/** /products/getlocationproducts?tenantid=&locationid=&subcategoryid=&pageno=&pagesize= —
* geofenced per-outlet inventory. */
export async function getProductLocations(opts: {
tenantid: number;
@@ -747,7 +755,7 @@ export async function getProductLocations(opts: {
pagesize?: number;
}): Promise<Row[]> {
return toRows(
await fiestaGet('products/getproductlocations', {
await fiestaGet('products/getlocationproducts', {
tenantid: opts.tenantid,
locationid: opts.locationid,
subcategoryid: opts.subcategoryid,
@@ -783,13 +791,35 @@ export interface CreateProductLocationInput {
tenantid: number;
locationid: number;
productid: number;
qty: number;
quantity?: number; // User prompt specified quantity
qty?: number; // Keep for backwards compatibility if needed
stocktype?: string;
status?: string;
price?: number;
}
/** POST /products/createproductlocation — Add a product to a store catalogue / inventory. */
/** POST /products/createproductlocation — Add a product to a store catalogue / inventory. (Expects array payload) */
export async function createProductLocation(input: CreateProductLocationInput): Promise<Row> {
return fiestaSend<Row>('products/createproductlocation', 'POST', input);
const payload = {
tenantid: input.tenantid,
locationid: input.locationid,
productid: input.productid,
quantity: input.quantity ?? input.qty ?? 0,
stocktype: input.stocktype || 'in',
status: input.status || 'Active',
};
return fiestaSend<Row>('products/createproductlocation', 'POST', [payload]);
}
export interface DeleteProductLocationInput {
tenantid: number;
locationid: number;
productid: number;
}
/** DELETE /products/deleteproductlocation — Remove a product from a store catalogue. */
export async function deleteProductLocation(input: DeleteProductLocationInput): Promise<Row> {
return fiestaSend<Row>('products/deleteproductlocation', 'DELETE', input);
}
export interface StockRequestInput {
@@ -1211,3 +1241,40 @@ export async function getSalesSummary(opts: {
const res = await fiestaGet<{ details: SalesSummaryResponse }>('v1/web/reports/sales-summary', opts);
return res.details;
}
// ════════════════════════════════════════════════════════════════════════════
// GLOBAL CATALOGUE
// ════════════════════════════════════════════════════════════════════════════
/** GET /v1/web/catalogue/getbrands — List all brands + product count per brand */
export async function getGlobalBrands(): Promise<Row[]> {
return toRows(await fiestaGet('catalogue/getbrands'));
}
/** GET /v1/web/catalogue/getcategories — List categories available for that brand */
export async function getGlobalCategories(opts: { brand: string }): Promise<string[]> {
const res = await fiestaGet<{ details: string[] }>('catalogue/getcategories', { brand: opts.brand });
return Array.isArray(res.details) ? res.details : [];
}
/** GET /v1/web/catalogue/getproducts — Product list */
export async function getGlobalProducts(opts: {
brand: string;
category?: string;
keyword?: string;
pageno?: number;
pagesize?: number;
}): Promise<Row[]> {
return toRows(await fiestaGet('catalogue/getproducts', {
brand: opts.brand,
category: opts.category,
keyword: opts.keyword,
pageno: opts.pageno,
pagesize: opts.pagesize,
}));
}
/** GET /v1/web/catalogue/getproduct — Single product lookup by SKU */
export async function getGlobalProduct(opts: { brand: string; sku: string }): Promise<Row | null> {
return firstRow(await fiestaGet('catalogue/getproduct', { brand: opts.brand, sku: opts.sku }));
}