Update sales.ts

This commit is contained in:
ssbg04 authored and GitHub committed 2025-12-06 13:21:50 +08:00
1 parent 46d422fa2f
commit 713fa271b7
1 file changed
+42 -43
+42 -43
View File
@@ -1,3 +1,4 @@
// ... existing imports and interfaces ...
export interface SaleItem { export interface SaleItem {
product_name: string; product_name: string;
quantity: number; quantity: number;
@@ -6,7 +7,7 @@ export interface SaleItem {
} }
export interface Sale { export interface Sale {
id?: string; id?: string; // Make sure ID is optional in interface
customer_name: string | null; customer_name: string | null;
amount_tendered: number; amount_tendered: number;
user_name: string; user_name: string;
@@ -19,12 +20,11 @@ export interface Sale {
payment_type: string; payment_type: string;
items: SaleItem[]; items: SaleItem[];
sale_date: string; sale_date: string;
status: "completed" | "void" | "refunded"; status: string;
discount_type: string; discount_type: string;
} }
const API_URL = const API_URL = "https://firestore.googleapis.com/v1/projects/pos-system-22c92/databases/(default)/documents/sales";
"https://firestore.googleapis.com/v1/projects/pos-system-22c92/databases/(default)/documents/sales";
// Helper to unwrap Firestore values // Helper to unwrap Firestore values
const unwrapValue = (field: any) => { const unwrapValue = (field: any) => {
@@ -42,24 +42,22 @@ export const getSales = async (): Promise<Sale[]> => {
let sales: Sale[] = []; let sales: Sale[] = [];
let nextPageToken: string | null = null; let nextPageToken: string | null = null;
// Loop to fetch ALL pages of data
do { do {
try { try {
const queryParams = new URLSearchParams({ pageSize: "300" }); const queryParams = new URLSearchParams({ pageSize: '300' });
if (nextPageToken) queryParams.append("pageToken", nextPageToken); if (nextPageToken) queryParams.append('pageToken', nextPageToken);
const response = await fetch(`${API_URL}?${queryParams.toString()}`); const response = await fetch(`${API_URL}?${queryParams.toString()}`);
if (!response.ok) throw new Error(`HTTP Error: ${response.status}`); if (!response.ok) throw new Error(`HTTP Error: ${response.status}`);
const data = await response.json(); const data = await response.json();
nextPageToken = data.nextPageToken || null; nextPageToken = data.nextPageToken || null;
const rawList = data.documents || []; const rawList = data.documents || [];
const batch = rawList.map((doc: any) => { const batch = rawList.map((doc: any) => {
const id = doc.name ? doc.name.split("/").pop() : "unknown"; const id = doc.name ? doc.name.split('/').pop() : 'unknown';
const fields = doc.fields || {}; const fields = doc.fields || {};
// Unwrap Items Array manually since it's nested
const itemsWrapper = fields.items?.arrayValue?.values || []; const itemsWrapper = fields.items?.arrayValue?.values || [];
const items: SaleItem[] = itemsWrapper.map((item: any) => ({ const items: SaleItem[] = itemsWrapper.map((item: any) => ({
product_name: unwrapValue(item.mapValue.fields.product_name), product_name: unwrapValue(item.mapValue.fields.product_name),
@@ -72,22 +70,23 @@ export const getSales = async (): Promise<Sale[]> => {
id, id,
customer_name: unwrapValue(fields.customer_name), customer_name: unwrapValue(fields.customer_name),
amount_tendered: unwrapValue(fields.amount_tendered) || 0, amount_tendered: unwrapValue(fields.amount_tendered) || 0,
user_name: unwrapValue(fields.user_name) || "Unknown", user_name: unwrapValue(fields.user_name) || 'Unknown',
tax_amount: unwrapValue(fields.tax_amount) || 0, tax_amount: unwrapValue(fields.tax_amount) || 0,
refund_reason: unwrapValue(fields.refund_reason), refund_reason: unwrapValue(fields.refund_reason),
total_amount: unwrapValue(fields.total_amount) || 0, total_amount: unwrapValue(fields.total_amount) || 0,
discount_amount: unwrapValue(fields.discount_amount) || 0, discount_amount: unwrapValue(fields.discount_amount) || 0,
change_due: unwrapValue(fields.change_due) || 0, change_due: unwrapValue(fields.change_due) || 0,
refunded_at: unwrapValue(fields.refunded_at), refunded_at: unwrapValue(fields.refunded_at),
payment_type: unwrapValue(fields.payment_type) || "Cash", payment_type: unwrapValue(fields.payment_type) || 'Cash',
items, items,
sale_date: unwrapValue(fields.sale_date), sale_date: unwrapValue(fields.sale_date),
status: unwrapValue(fields.status) || "completed", status: unwrapValue(fields.status) || 'completed',
discount_type: unwrapValue(fields.discount_type) || "None", discount_type: unwrapValue(fields.discount_type) || 'None'
}; };
}); });
sales = [...sales, ...batch]; sales = [...sales, ...batch];
} catch (error) { } catch (error) {
console.error("Failed to fetch sales page:", error); console.error("Failed to fetch sales page:", error);
throw error; throw error;
@@ -97,36 +96,30 @@ export const getSales = async (): Promise<Sale[]> => {
return sales; return sales;
}; };
export const updateSaleStatus = async ( export const updateSaleStatus = async (id: string, status: 'void' | 'refunded', reason: string): Promise<void> => {
id: string,
status: "void" | "refunded",
reason: string
): Promise<void> => {
const url = `${API_URL}/${id}?updateMask.fieldPaths=status&updateMask.fieldPaths=refund_reason&updateMask.fieldPaths=refunded_at`; const url = `${API_URL}/${id}?updateMask.fieldPaths=status&updateMask.fieldPaths=refund_reason&updateMask.fieldPaths=refunded_at`;
const now = new Date().toISOString(); const now = new Date().toISOString();
const response = await fetch(url, { const response = await fetch(url, {
method: "PATCH", method: 'PATCH',
headers: { "Content-Type": "application/json" }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ body: JSON.stringify({
fields: { fields: {
status: { stringValue: status }, status: { stringValue: status },
refund_reason: { stringValue: reason }, refund_reason: { stringValue: reason },
refunded_at: { timestampValue: now }, refunded_at: { timestampValue: now }
}, }
}), })
}); });
if (!response.ok) if (!response.ok) throw new Error(`Failed to update sale status: ${response.status}`);
throw new Error(`Failed to update sale status: ${response.status}`);
}; };
export const createSale = async (sale: Sale): Promise<void> => { // Updated to return string (The new ID)
export const createSale = async (sale: Sale): Promise<string> => {
const payload = { const payload = {
fields: { fields: {
customer_name: sale.customer_name customer_name: sale.customer_name ? { stringValue: sale.customer_name } : { nullValue: null },
? { stringValue: sale.customer_name }
: { nullValue: null },
amount_tendered: { doubleValue: sale.amount_tendered }, amount_tendered: { doubleValue: sale.amount_tendered },
user_name: { stringValue: sale.user_name }, user_name: { stringValue: sale.user_name },
tax_amount: { doubleValue: sale.tax_amount }, tax_amount: { doubleValue: sale.tax_amount },
@@ -141,30 +134,36 @@ export const createSale = async (sale: Sale): Promise<void> => {
discount_type: { stringValue: sale.discount_type }, discount_type: { stringValue: sale.discount_type },
items: { items: {
arrayValue: { arrayValue: {
values: sale.items.map((item) => ({ values: sale.items.map(item => ({
mapValue: { mapValue: {
fields: { fields: {
product_name: { stringValue: item.product_name }, product_name: { stringValue: item.product_name },
quantity: { integerValue: String(item.quantity) }, quantity: { integerValue: String(item.quantity) },
price: { doubleValue: item.price }, price: { doubleValue: item.price },
total: { doubleValue: item.total }, total: { doubleValue: item.total }
}, }
}, }
})), }))
}, }
}, }
}, }
}; };
const response = await fetch(API_URL, { const response = await fetch(API_URL, {
method: "POST", method: 'POST',
headers: { "Content-Type": "application/json" }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload), body: JSON.stringify(payload)
}); });
if (!response.ok) { if (!response.ok) {
// @ts-ignore
const errText = await response.text(); const errText = await response.text();
throw new Error(`Failed to create sale: ${response.status}`); throw new Error(`Failed to create sale: ${response.status}`);
} }
// Parse response to get the ID
const data = await response.json();
// data.name is like "projects/.../documents/sales/DOCUMENT_ID"
const newId = data.name.split('/').pop();
return newId;
}; };