fix : print and transaction summary fixed

This commit is contained in:
Sibin Sabu 2025-08-09 12:19:09 +05:30
parent 5919f589e2
commit 11a9f2013e
4 changed files with 452 additions and 130 deletions

View File

@ -83,8 +83,16 @@ export class MiddleSectionComponent implements OnInit, OnDestroy {
console.error('❌ Failed to parse localTickets from localStorage:', e);
}
this.salesTotal = this.grandTotal + storedTotal;
this.receiveTotal = this.salesTotal;
// 👇 Only show printed totals until print happens
const hasPrinted = localStorage.getItem('hasPrinted') === 'true';
if (hasPrinted) {
this.salesTotal = storedTotal;
this.receiveTotal = storedTotal;
} else {
this.salesTotal = storedTotal; // do NOT include grandTotal yet
this.receiveTotal = storedTotal;
}
this.totalClicks = Number(localStorage.getItem('printClickCount') || '0');
// 👇 Toggle visibility based on localStorage flag
@ -156,7 +164,7 @@ export class MiddleSectionComponent implements OnInit, OnDestroy {
// })
// .filter(Boolean) as SelectionData[];
// }
repeat() {
repeat() {
try {
const storedTickets = localStorage.getItem('localTicketsnew');
if (storedTickets) {
@ -191,11 +199,11 @@ repeat() {
}
parseWinLabelsToRows(winLabels: string, fallbackTotal?: number): SelectionData[] {
return (winLabels.split('\n') as string[])
.map(line => {
return (winLabels.split('\n') as string[])
.map(line => {
// Match: LABEL NUMBERS *VALUE [Rs TOTAL optional]
const match = line.match(/^(\S+)\s+(.+?)\s+\*([\d.]+)(?:\s*(?:Rs)?\s*(\d+))?/);
if (!match) return null;
if (!match) return null;
const label = match[1].trim();
const numbersRaw = match[2].trim();
@ -212,18 +220,16 @@ parseWinLabelsToRows(winLabels: string, fallbackTotal?: number): SelectionData[]
numbers = numbersRaw.split(',').map(s => s.trim()).filter(Boolean);
}
return {
return {
label,
numbers,
value,
total,
isBoxed: numbersRaw.startsWith('#')
};
})
.filter(Boolean) as SelectionData[];
}
};
})
.filter(Boolean) as SelectionData[];
}
confirm() {
this.showPrintButton = true; // Show Print button after confirming
@ -233,20 +239,20 @@ parseWinLabelsToRows(winLabels: string, fallbackTotal?: number): SelectionData[]
//-----------------------REPEAT PRINT LOGIC ----------------------------------
printRepeat() {
console.log('🖨️ [DEBUG] Printing ticket...');
console.log('🖨️ [DEBUG] Printing ticket...');
const userName = localStorage.getItem('userName') || 'Unknown';
const currentDate = new Date().toLocaleString();
const currentDate = new Date().toLocaleString();
const printableRows = this.filledRows
.filter(row => row.label && row.numbers.length > 0 && row.total > 0)
.map(row => {
const horses = Array.isArray(row.numbers) ? row.numbers.join(',') : row.numbers;
return `${row.label.padEnd(6)} ${horses.padEnd(15)} * ${String(row.value).padEnd(3)}${row.total}`;
})
.join('\n');
const printableRows = this.filledRows
.filter(row => row.label && row.numbers.length > 0 && row.total > 0)
.map(row => {
const horses = Array.isArray(row.numbers) ? row.numbers.join(',') : row.numbers;
return `${row.label.padEnd(6)} ${horses.padEnd(15)} * ${String(row.value).padEnd(3)}${row.total}`;
})
.join('\n');
const ticketContent = `
const ticketContent = `
=================================
🏇 BTC Race Ticket 🏇
=================================
@ -257,37 +263,68 @@ Date : ${currentDate}
=================================
`;
// ✅ Log preview in console
console.log('%c\n' + ticketContent, 'font-family: monospace; color: green');
// ✅ Log preview in console
console.log('%c\n' + ticketContent, 'font-family: monospace; color: green');
// ✅ Send to print server
const payload = {
type: 'repeat',
// ✅ Send to print server
const payload = {
type: 'repeat',
printedBy: userName,
content: ticketContent,
timestamp: currentDate
};
content: ticketContent,
timestamp: currentDate
};
fetch('http://localhost:9100/print', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
})
.then(response => {
if (!response.ok) throw new Error(`Printer error: ${response.status}`);
return response.text();
})
.then(result => {
console.log("✅ Repeat ticket print successful:", result);
})
.catch(error => {
console.error("❌ Repeat ticket print failed:", error);
});
fetch('http://localhost:9100/print', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
})
.then(response => {
if (!response.ok) throw new Error(`Printer error: ${response.status}`);
return response.text();
})
.then(result => {
console.log("✅ Repeat ticket print successful:", result);
})
.catch(error => {
console.error("❌ Repeat ticket print failed:", error);
});
this.showConfirmButton = false;
this.showPrintButton = false;
this.erase(); // Clear selections after printing
// --- Update localStorage for transaction summary like normal print ---
// 1. Increment printClickCount
let clickCount = Number(localStorage.getItem('printClickCount') || '0');
clickCount += 1;
localStorage.setItem('printClickCount', clickCount.toString());
// 2. Add a new ticket entry to localTickets (type: 'ticket', totalAmount)
try {
const existingTicketsStr = localStorage.getItem('localTickets');
const existingTickets = existingTicketsStr ? JSON.parse(existingTicketsStr) : [];
// Calculate totalAmount for this repeat print
const totalAmount = this.filledRows
.filter(row => row.label && row.numbers.length > 0 && row.total > 0)
.reduce((sum, row) => sum + (row.total || 0), 0);
const ticketEntry = {
type: 'ticket',
printedBy: userName,
totalAmount,
content: ticketContent,
timestamp: currentDate
};
existingTickets.push(ticketEntry);
localStorage.setItem('localTickets', JSON.stringify(existingTickets));
} catch (error) {
console.error('❌ Failed to update localTickets for repeat print:', error);
}
// Hide Confirm and Print buttons before clearing selections
this.showConfirmButton = false;
this.showPrintButton = false;
this.erase(); // Clear selections after hiding buttons
// 👉 Recalculate totals after erase to update transaction summary
this.calculateTotal();
}
@ -295,9 +332,12 @@ Date : ${currentDate}
erase() {
this.selectionService.clearSelections();
this.resetSelections();
// 👉 Also recalculate totals after erase to keep summary in sync
this.calculateTotal();
}
resetSelections() {
throw new Error('Method not implemented.');
// No-op: Prevent error and allow summary to update
// (If you want to reset any local state, do it here)
}
ngOnDestroy() {
this.sub1.unsubscribe();

View File

@ -481,37 +481,70 @@ openViewLog() {
}
logout(): void {
const name = localStorage.getItem('userName') || 'Unknown User';
const employeeId = localStorage.getItem('employeeId') || '000000';
const printData = {
name,
employeeId,
action: 'logout',
type: 'logout' // 👈 This is the missing piece
};
console.log('[LOGOUT] Initiating logout with printData:', printData);
logout(): void {
const name = localStorage.getItem('userName') || 'Unknown User';
const employeeId = localStorage.getItem('employeeId') || '000000';
const printData = { name, employeeId, action: 'logout' };
console.log('[LOGOUT] Initiating logout with printData:', printData);
fetch('http://localhost:9100/print', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(printData),
fetch('http://localhost:9100/print', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(printData),
})
.then((res) => {
if (!res.ok) throw new Error('Logout print failed');
console.log('[LOGOUT] Print successful');
(window as any).electronAPI?.closeSecondScreen?.();
localStorage.clear();
this.router.navigate(['/logout']);
})
.then((res) => {
if (!res.ok) throw new Error('Logout print failed');
console.log('[LOGOUT] Print successful');
(window as any).electronAPI?.closeSecondScreen?.();
localStorage.clear();
this.router.navigate(['/logout']);
})
.catch((err) => {
console.error('[LOGOUT] Error printing:', err);
(window as any).electronAPI?.closeSecondScreen?.();
localStorage.clear();
this.router.navigate(['/logout']);
});
}
.catch((err) => {
console.error('[LOGOUT] Error printing:', err);
(window as any).electronAPI?.closeSecondScreen?.();
localStorage.clear();
this.router.navigate(['/logout']);
});
}
// logout(): void {
// const name = localStorage.getItem('userName') || 'Unknown User';
// const employeeId = localStorage.getItem('employeeId') || '000000';
// const printData = { name, employeeId, action: 'logout' };
// console.log('[LOGOUT] Initiating logout with printData:', printData);
// fetch('http://localhost:9100/print', {
// method: 'POST',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify(printData),
// })
// .then((res) => {
// if (!res.ok) throw new Error('Logout print failed');
// console.log('[LOGOUT] Print successful');
// (window as any).electronAPI?.closeSecondScreen?.();
// localStorage.clear();
// this.router.navigate(['/logout']);
// })
// .catch((err) => {
// console.error('[LOGOUT] Error printing:', err);
// (window as any).electronAPI?.closeSecondScreen?.();
// localStorage.clear();
// this.router.navigate(['/logout']);
// });
// }
ngOnDestroy(): void {
if (this.subscription) {

View File

@ -50,16 +50,103 @@ export class SidebarComponent {
//---------------------------------------ADDED THE CANCEL PRINT ---------------------------
cancelWarning: string = ''; // For showing inline warnings
// printTicketCancel() {
// const enteredTicketNo = this.ticketNo?.trim();
// console.log('[STEP 1] Entered Ticket No:', enteredTicketNo);
// this.cancelWarning = '';
// const localTicketsStr = localStorage.getItem('localTicketsnew');
// if (!localTicketsStr) {
// console.error('[STEP 2] No localTickets found in localStorage.');
// this.cancelWarning = '❌ No ticket history found.';
// return;
// }
// let localTickets;
// try {
// localTickets = JSON.parse(localTicketsStr);
// } catch (e) {
// console.error('[STEP 3] Error parsing localTickets:', e);
// this.cancelWarning = '❌ Error reading stored tickets.';
// return;
// }
// if (!Array.isArray(localTickets) || localTickets.length === 0) {
// console.warn('[STEP 4] localTickets is empty.');
// this.cancelWarning = '❌ No tickets available to verify.';
// return;
// }
// const lastTicket = localTickets[localTickets.length - 1];
// console.log('[STEP 5] Last Ticket:', lastTicket);
// if (!lastTicket || !lastTicket.barcodeId) {
// console.warn('[STEP 6] Last ticket missing barcodeId.');
// this.cancelWarning = '❌ Invalid stored ticket.';
// return;
// }
// const storedBarcode = lastTicket.barcodeId.trim();
// console.log('[STEP 7] Stored Barcode ID:', storedBarcode);
// if (enteredTicketNo === storedBarcode) {
// console.log('[✅ MATCH] Ticket No matches barcode. Proceeding to print...');
// // 🧾 Construct cancel print layout (only showing total from original ticket)
// const cancelTicketData = {
// type: 'CANCEL_TICKET',
// ticketId: lastTicket.ticketId || '',
// barcodeId: lastTicket.barcodeId,
// cancelDate: new Date().toLocaleString(),
// total: lastTicket.total || 0 // <-- only keeping total
// };
// // 🔍 Console Preview
// console.log('🧾 [CANCEL TICKET LAYOUT]');
// console.log(`
// ========================================
// ⚠️ TICKET CANCELLED ⚠️
// ----------------------------------------
// Ticket ID : ${cancelTicketData.ticketId}
// Barcode ID : ${cancelTicketData.barcodeId}
// Cancelled At : ${cancelTicketData.cancelDate}
// Original Total: ₹${cancelTicketData.total}
// ========================================
// `);
// // 🖨️ Send to printer server
// fetch('http://localhost:9100/print', {
// method: 'POST',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify(cancelTicketData)
// })
// .then(response => {
// if (!response.ok) throw new Error(`Printer error: ${response.status}`);
// return response.text();
// })
// .then(result => {
// console.log("✅ Cancel ticket print successful:", result);
// })
// .catch(error => {
// console.error("❌ Cancel ticket print failed:", error);
// });
// this.closeCancelPopup();
// } else {
// console.warn('[❌ MISMATCH] Entered Ticket No does NOT match last stored barcode.');
// this.cancelWarning = '❌ Invalid ticket number. Please check and try again.';
// }
// }
printTicketCancel() {
const enteredTicketNo = this.ticketNo?.trim();
console.log('[STEP 1] Entered Ticket No:', enteredTicketNo);
this.cancelWarning = '';
const localTicketsStr = localStorage.getItem('localTickets');
const localTicketsStr = localStorage.getItem('localTicketsnew');
if (!localTicketsStr) {
console.error('[STEP 2] No localTickets found in localStorage.');
this.cancelWarning = '❌ No ticket history found.';
this.cancelWarning = '❌ No ticket history found.';
return;
}
@ -93,31 +180,29 @@ printTicketCancel() {
if (enteredTicketNo === storedBarcode) {
console.log('[✅ MATCH] Ticket No matches barcode. Proceeding to print...');
// 🧾 Construct cancel print layout (DEMO)
// 🧾 Construct cancel print layout (only totalAmount)
const cancelTicketData = {
type: 'CANCEL_TICKET',
ticketId: lastTicket.ticketId || '',
barcodeId: lastTicket.barcodeId,
cancelDate: new Date().toLocaleString(),
originalTicket: lastTicket
totalAmount: lastTicket.totalAmount || 0 // <-- only totalAmount
};
// 🔍 DEMO CONSOLE PRINT LAYOUT
// 🔍 Console Preview
console.log('🧾 [CANCEL TICKET LAYOUT]');
console.log(`
========================================
TICKET CANCELLED
----------------------------------------
Ticket ID : ${cancelTicketData.ticketId}
Barcode ID : ${cancelTicketData.barcodeId}
Cancelled At : ${cancelTicketData.cancelDate}
Original Ticket:
${JSON.stringify(cancelTicketData.originalTicket, null, 2)}
Ticket ID : ${cancelTicketData.ticketId}
Barcode ID : ${cancelTicketData.barcodeId}
Cancelled At : ${cancelTicketData.cancelDate}
Original Total: ${cancelTicketData.totalAmount}
========================================
`);
// 🖨️ SEND TO PORT 9100
// 🖨️ Send to printer server
fetch('http://localhost:9100/print', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
@ -143,6 +228,97 @@ ${JSON.stringify(cancelTicketData.originalTicket, null, 2)}
}
// printTicketCancel() {
// const enteredTicketNo = this.ticketNo?.trim();
// console.log('[STEP 1] Entered Ticket No:', enteredTicketNo);
// this.cancelWarning = '';
// const localTicketsStr = localStorage.getItem('localTicketsnew');
// if (!localTicketsStr) {
// console.error('[STEP 2] No localTickets found in localStorage.');
// this.cancelWarning = '❌ No ticket history found.';
// return;
// }
// let localTickets;
// try {
// localTickets = JSON.parse(localTicketsStr);
// } catch (e) {
// console.error('[STEP 3] Error parsing localTickets:', e);
// this.cancelWarning = '❌ Error reading stored tickets.';
// return;
// }
// if (!Array.isArray(localTickets) || localTickets.length === 0) {
// console.warn('[STEP 4] localTickets is empty.');
// this.cancelWarning = '❌ No tickets available to verify.';
// return;
// }
// const lastTicket = localTickets[localTickets.length - 1];
// console.log('[STEP 5] Last Ticket:', lastTicket);
// if (!lastTicket || !lastTicket.barcodeId) {
// console.warn('[STEP 6] Last ticket missing barcodeId.');
// this.cancelWarning = '❌ Invalid stored ticket.';
// return;
// }
// const storedBarcode = lastTicket.barcodeId.trim();
// console.log('[STEP 7] Stored Barcode ID:', storedBarcode);
// if (enteredTicketNo === storedBarcode) {
// console.log('[✅ MATCH] Ticket No matches barcode. Proceeding to print...');
// // 🧾 Construct cancel print layout (DEMO)
// const cancelTicketData = {
// type: 'CANCEL_TICKET',
// ticketId: lastTicket.ticketId || '',
// barcodeId: lastTicket.barcodeId,
// cancelDate: new Date().toLocaleString(),
// originalTicket: lastTicket
// };
// // 🔍 DEMO CONSOLE PRINT LAYOUT
// console.log('🧾 [CANCEL TICKET LAYOUT]');
// console.log(`
// ========================================
// ⚠️ TICKET CANCELLED ⚠️
// ----------------------------------------
// Ticket ID : ${cancelTicketData.ticketId}
// Barcode ID : ${cancelTicketData.barcodeId}
// Cancelled At : ${cancelTicketData.cancelDate}
// ❗ Original Ticket:
// ${JSON.stringify(cancelTicketData.originalTicket, null, 2)}
// ========================================
// `);
// // 🖨️ SEND TO PORT 9100
// fetch('http://localhost:9100/print', {
// method: 'POST',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify(cancelTicketData)
// })
// .then(response => {
// if (!response.ok) throw new Error(`Printer error: ${response.status}`);
// return response.text();
// })
// .then(result => {
// console.log("✅ Cancel ticket print successful:", result);
// })
// .catch(error => {
// console.error("❌ Cancel ticket print failed:", error);
// });
// this.closeCancelPopup();
// } else {
// console.warn('[❌ MISMATCH] Entered Ticket No does NOT match last stored barcode.');
// this.cancelWarning = '❌ Invalid ticket number. Please check and try again.';
// }
// }
//--------------------------------COMPLETED THE CANCEL PRINT ---------------------------------------
openPayoutPopup() {
@ -336,22 +512,82 @@ Date : ${new Date().toLocaleString()}
// this.closeDepositPopup();
// }
// ==============================
// 💰 DEPOSIT RECEIPT
// ==============================
// Operator ID : ${this.depositOperatorId}
// Shroff ID : ${this.depositShroffId}
// Amount : ₹${this.depositAmount}
// Printed By : ${userName}
// Date : ${new Date().toLocaleString()}
// ==============================
// printDeposit() {
// const userName = localStorage.getItem('userName') || 'Unknown';
// // 🖨️ Console log the exact print layout
// console.log(`
// ==============================
// 💰 DEPOSIT RECEIPT
// ==============================
// Operator ID : ${this.depositOperatorId}
// Shroff ID : ${this.depositShroffId}
// Amount : ₹${this.depositAmount}
// Printed By : ${userName}
// Date : ${new Date().toLocaleString()}
// ==============================
// 🧾 Denomination Voucher
// 1000 x _____________ = _____________
// 500 x _____________ = _____________
// 100 x _____________ = _____________
// 50 x _____________ = _____________
// 20 x _____________ = _____________
// 10 x _____________ = _____________
// 5 x _____________ = _____________
// ==============================
// `);
// // ✅ Send to print server
// const payload = {
// type: 'deposit',
// printedBy: userName,
// operatorId: this.depositOperatorId,
// shroffId: this.depositShroffId,
// amount: this.depositAmount,
// //content: receiptText
// };
// fetch('http://localhost:9100/print', {
// method: 'POST',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify(payload)
// })
// .then(response => {
// if (!response.ok) throw new Error(`Printer error: ${response.status}`);
// return response.text();
// })
// .then(result => {
// console.log("✅ Deposit print successful:", result);
// })
// .catch(error => {
// console.error("❌ Deposit print failed:", error);
// });
// this.closeDepositPopup();
// }
printDeposit() {
const userName = localStorage.getItem('userName') || 'Unknown';
const receiptText = `
==============================
💰 DEPOSIT RECEIPT
==============================
Operator ID : ${this.depositOperatorId}
Shroff ID : ${this.depositShroffId}
Amount : ${this.depositAmount}
Printed By : ${userName}
Date : ${new Date().toLocaleString()}
==============================
// Denomination voucher section
const content = `
🧾 Denomination Voucher
1000 x _____________ = _____________
2000 x _____________ = _____________
500 x _____________ = _____________
100 x _____________ = _____________
50 x _____________ = _____________
@ -359,11 +595,32 @@ Date : ${new Date().toLocaleString()}
10 x _____________ = _____________
5 x _____________ = _____________
==============================
Total = ____________________________
=====================================
`;
// 🖨️ Console log the exact print layout
console.log("🖨️ DEPOSIT PRINT LAYOUT:\n" + receiptText);
// Full preview — matches backend print style
const now = new Date();
const date = now.toISOString().split('T')[0];
const time = now.toTimeString().split(' ')[0];
const previewReceipt = `
Bangalore Turf Club
DEPOSIT RECEIPT
-------------------------------
Operator : ${this.depositOperatorId || 'N/A'}
Shroff : ${this.depositShroffId || 'N/A'}
Amount : ${this.depositAmount}
Printed By: ${userName}
Date : ${date}
Time : ${time}
-------------------------------
${content}
`;
// 🖨️ Console log exactly what will be printed
console.log("🖨️ DEPOSIT PRINT LAYOUT:\n" + previewReceipt);
// ✅ Send to print server
const payload = {
@ -372,7 +629,7 @@ Date : ${new Date().toLocaleString()}
operatorId: this.depositOperatorId,
shroffId: this.depositShroffId,
amount: this.depositAmount,
content: receiptText
content: content
};
fetch('http://localhost:9100/print', {
@ -476,18 +733,8 @@ printWithdraw() {
const userName = localStorage.getItem('userName') || 'Unknown';
const receiptText = `
==============================
💸 WITHDRAW RECEIPT
==============================
Operator ID : ${this.withdrawOperatorId}
Shroff ID : ${this.withdrawShroffId}
Amount : ${this.withdrawAmount}
Printed By : ${userName}
Date : ${new Date().toLocaleString()}
==============================
🧾 Denomination Voucher
1000 x _____________ = _____________
2000 x _____________ = _____________
500 x _____________ = _____________
100 x _____________ = _____________
50 x _____________ = _____________
@ -495,7 +742,9 @@ Date : ${new Date().toLocaleString()}
10 x _____________ = _____________
5 x _____________ = _____________
==============================
Total = ____________________________
=====================================
`;
// 🖨️ Log the exact print layout

View File

@ -251,24 +251,24 @@ export class LoginComponent implements OnInit, OnDestroy {
localStorage.setItem('password', password);
// Optional print logic
// fetch('http://localhost:9100/print', {
// method: 'POST',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify(printData),
// })
// .then((res) => {
// if (!res.ok) throw new Error('Print failed');
// console.log('🖨️ Print successful');
fetch('http://localhost:9100/print', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(printData),
})
.then((res) => {
if (!res.ok) throw new Error('Print failed');
console.log('🖨️ Print successful');
// Open second screen
(window as any).electronAPI?.openSecondScreen?.();
// // Navigate to home
this.router.navigate(['/home']);
// })
// .catch((err) => {
// console.error('‼️ Print failed', err);
// this.loginError = 'Login OK, but printing failed.';
// });
})
.catch((err) => {
console.error('‼️ Print failed', err);
this.loginError = 'Login OK, but printing failed.';
});
},