WIP quickbooks testing.
This commit is contained in:
1597
package-lock.json
generated
1597
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -25,7 +25,8 @@
|
||||
"@electron-toolkit/utils": "^4.0.0",
|
||||
"electron-log": "^5.3.2",
|
||||
"electron-store": "^8.2.0",
|
||||
"electron-updater": "^6.3.9"
|
||||
"electron-updater": "^6.3.9",
|
||||
"winax": "^3.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ant-design/v5-patch-for-react-19": "^1.0.3",
|
||||
|
||||
BIN
resources/Interop.QBFC16.dll
Normal file
BIN
resources/Interop.QBFC16.dll
Normal file
Binary file not shown.
BIN
resources/Interop.QBXMLRP2.dll
Normal file
BIN
resources/Interop.QBXMLRP2.dll
Normal file
Binary file not shown.
BIN
resources/QBFC16.dll
Normal file
BIN
resources/QBFC16.dll
Normal file
Binary file not shown.
@@ -2,6 +2,8 @@ import cors from "cors";
|
||||
import { app } from "electron";
|
||||
import log from "electron-log/main";
|
||||
import express from "express";
|
||||
import { handleQuickBookRequest } from "../quickbooks-desktop/quickbooks-desktop";
|
||||
import errorTypeCheck from "../../util/errorTypeCheck";
|
||||
|
||||
export default class LocalServer {
|
||||
private app: express.Application;
|
||||
@@ -94,7 +96,7 @@ export default class LocalServer {
|
||||
|
||||
private configureRoutes(): void {
|
||||
// Basic health check endpoint
|
||||
this.app.get("/health", (req, res) => {
|
||||
this.app.get("/health", (req: express.Request, res: express.Response) => {
|
||||
res.status(200).json({ status: "ok" });
|
||||
});
|
||||
this.app.post("/ping", (req, res) => {
|
||||
@@ -103,13 +105,25 @@ export default class LocalServer {
|
||||
qbPath: app.getPath("userData"), //TODO: Resolve to actual QB file path.
|
||||
});
|
||||
});
|
||||
|
||||
this.app.post("/qb", handleQuickBookRequest);
|
||||
// Add more routes as needed
|
||||
}
|
||||
|
||||
public start(): void {
|
||||
this.server = this.app.listen(this.PORT, () => {
|
||||
log.info(`[HTTP Server] Local HTTP server running on port ${this.PORT}`);
|
||||
});
|
||||
try {
|
||||
this.server = this.app.listen(this.PORT, (error: Error) => {
|
||||
if (error) {
|
||||
log.error(`[HTTP Server] Error starting server: ${error}`);
|
||||
} else {
|
||||
log.info(
|
||||
`[HTTP Server] Local HTTP server running on port ${this.PORT}`,
|
||||
);
|
||||
}
|
||||
});
|
||||
} catch (error: unknown) {
|
||||
log.error("[HTTP Server] Error starting server", errorTypeCheck(error));
|
||||
}
|
||||
}
|
||||
|
||||
public stop(): void {
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
import { electronApp, is, optimizer } from "@electron-toolkit/utils";
|
||||
import { app, BrowserWindow, Menu, shell, nativeImage, Tray } from "electron";
|
||||
import { app, BrowserWindow, Menu, nativeImage, shell, Tray } from "electron";
|
||||
import log from "electron-log/main";
|
||||
import { autoUpdater } from "electron-updater";
|
||||
import path, { join } from "path";
|
||||
import appIcon from "../../resources/diamond.png?asset";
|
||||
import icon from "../../resources/icon.png?asset";
|
||||
import ErrorTypeCheck from "../util/errorTypeCheck";
|
||||
import {
|
||||
default as ErrorTypeCheck,
|
||||
default as errorTypeCheck,
|
||||
} from "../util/errorTypeCheck";
|
||||
import ipcTypes from "../util/ipcTypes.json";
|
||||
import client from "./graphql/graphql-client";
|
||||
import store from "./store/store";
|
||||
import appIcon from "../../resources/diamond.png?asset";
|
||||
import LocalServer from "./http-server/http-server";
|
||||
import errorTypeCheck from "../util/errorTypeCheck";
|
||||
import store from "./store/store";
|
||||
import { TestQB } from "./quickbooks-desktop/quickbooks-desktop";
|
||||
|
||||
log.initialize();
|
||||
const isMac = process.platform === "darwin";
|
||||
@@ -171,20 +174,9 @@ function createWindow(): void {
|
||||
type: "separator",
|
||||
},
|
||||
{
|
||||
label: "Temp Test Action - Get Token from Renderer",
|
||||
label: "Temp Test Action",
|
||||
click: (): void => {
|
||||
client
|
||||
.request(
|
||||
`
|
||||
query jobs{
|
||||
jobs
|
||||
{
|
||||
id}}
|
||||
`,
|
||||
)
|
||||
.then((data) => {
|
||||
log.info("Data from graffle", data);
|
||||
});
|
||||
TestQB();
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
30
src/main/quickbooks-desktop/QuickbooksConnector.cs
Normal file
30
src/main/quickbooks-desktop/QuickbooksConnector.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using Interop.QBFC16; // Ensure this matches your DLL version
|
||||
|
||||
public class QuickBooksConnector
|
||||
{
|
||||
public string ProcessQBXML(string qbxmlRequest)
|
||||
{
|
||||
try
|
||||
{
|
||||
QBSessionManager sessionManager = new QBSessionManager();
|
||||
sessionManager.OpenConnection("", "YourAppName");
|
||||
sessionManager.BeginSession("", ENOpenMode.omDontCare);
|
||||
|
||||
IMsgSetRequest requestMsgSet = sessionManager.CreateMsgSetRequest("US", 13, 0);
|
||||
requestMsgSet.AppendXML(qbxmlRequest);
|
||||
|
||||
IMsgSetResponse responseMsgSet = sessionManager.DoRequests(requestMsgSet);
|
||||
string qbxmlResponse = responseMsgSet.ToXMLString();
|
||||
|
||||
sessionManager.EndSession();
|
||||
sessionManager.CloseConnection();
|
||||
|
||||
return qbxmlResponse;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return $"Error: {ex.Message}";
|
||||
}
|
||||
}
|
||||
}
|
||||
114
src/main/quickbooks-desktop/quickbooks-desktop.ts
Normal file
114
src/main/quickbooks-desktop/quickbooks-desktop.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import * as Winax from "winax";
|
||||
import log from "electron-log/main";
|
||||
|
||||
import { Request, Response } from "express";
|
||||
import { UUID } from "crypto";
|
||||
import errorTypeCheck from "../../util/errorTypeCheck";
|
||||
import _ from "lodash";
|
||||
import store from "../store/store";
|
||||
|
||||
export async function handleQuickBookRequest(
|
||||
req: Request,
|
||||
res: Response,
|
||||
): Promise<void> {
|
||||
//TODO: Add OS sysstem checking. This can only happen on windows machines.
|
||||
const QbFilePath: string = `C:\\Users\\PatrickFic\\Development\\FRODO COLLISION.QBW`;
|
||||
// ||
|
||||
// (store.get("settings.qbFilePath") as string) F
|
||||
|
||||
if (_.isEmpty(QbFilePath)) {
|
||||
res.status(400).json({ error: "Quickbooks file path not set" });
|
||||
return;
|
||||
}
|
||||
|
||||
const qbxmlRequestList = req.body as Array<{
|
||||
id: UUID;
|
||||
okStatusCodes: Array<string>;
|
||||
qbxml: string;
|
||||
}>;
|
||||
|
||||
const returnResponse: Array<{
|
||||
Id: UUID;
|
||||
Success: boolean;
|
||||
ErrorMessage: string;
|
||||
}> = [];
|
||||
|
||||
//Connect to the QuickBooks File
|
||||
let requestProcessor;
|
||||
try {
|
||||
requestProcessor = new Winax.Object("QBXMLRP2.RequestProcessor.2");
|
||||
requestProcessor.OpenConnection(QbFilePath, "ShopPartnerActualRequest");
|
||||
} catch (error) {
|
||||
log.error(
|
||||
"Error instnatiating QuickBooks Request Processor",
|
||||
QbFilePath,
|
||||
errorTypeCheck(error),
|
||||
);
|
||||
res.status(500).json({ error: "Error connecting to QuickBooks" });
|
||||
return;
|
||||
}
|
||||
|
||||
const ticket = requestProcessor.BeginSession(QbFilePath, 2); //2 indicated qbFileOpenModeDoNotCare
|
||||
log.info("Quickbooks Ticket", ticket);
|
||||
for (const qbxmlRequest of qbxmlRequestList) {
|
||||
try {
|
||||
//TODO: Refactor to not create a new connection every time.
|
||||
const QuickBooksResponse = requestProcessor.ProcessRequest(
|
||||
ticket,
|
||||
qbxmlRequest.qbxml,
|
||||
);
|
||||
log.info("QuickBooks Raw Response: ", QuickBooksResponse);
|
||||
returnResponse.push({
|
||||
Id: qbxmlRequest.id,
|
||||
Success:
|
||||
QuickBooksResponse.StatusCode === "0" ||
|
||||
qbxmlRequest.okStatusCodes.includes(QuickBooksResponse.StatusCode),
|
||||
ErrorMessage: QuickBooksResponse,
|
||||
});
|
||||
} catch (error) {
|
||||
log.error(
|
||||
"Error running transaction",
|
||||
ticket,
|
||||
qbxmlRequest,
|
||||
errorTypeCheck(error),
|
||||
);
|
||||
}
|
||||
}
|
||||
requestProcessor.EndSession(ticket);
|
||||
requestProcessor.CloseConnection();
|
||||
res.json(qbxmlRequestList);
|
||||
}
|
||||
|
||||
//This set of functions works.
|
||||
export function TestQB(): void {
|
||||
let requestProcessor, ticket;
|
||||
try {
|
||||
requestProcessor = new Winax.Object("QBXMLRP.RequestProcessor.1");
|
||||
const connection = requestProcessor.OpenConnection("", "ShopPartnerOneoFf");
|
||||
|
||||
ticket = requestProcessor.BeginSession("", 2); //2 indicated qbFileOFpenModeDoNotCare
|
||||
|
||||
const qbre = requestProcessor.ProcessRequest(
|
||||
ticket,
|
||||
`<?qbxml version="16.0"?>
|
||||
<QBXML>
|
||||
<QBXMLMsgsRq onError="stopOnError">
|
||||
<AccountQueryRq requestID="1"> </AccountQueryRq>
|
||||
</QBXMLMsgsRq>
|
||||
</QBXML>`,
|
||||
);
|
||||
} catch (error) {
|
||||
log.error(
|
||||
"Error instnatiating QuickBooks Request Processor",
|
||||
|
||||
errorTypeCheck(error),
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
log.log("Ticket", ticket);
|
||||
requestProcessor.EndSession(ticket);
|
||||
requestProcessor.CloseConnection();
|
||||
return;
|
||||
}
|
||||
@@ -4,6 +4,7 @@ const store = new Store({
|
||||
defaults: {
|
||||
settings: {
|
||||
filepaths: [],
|
||||
qbFilePath: "",
|
||||
runWatcherOnStartup: true,
|
||||
polling: {
|
||||
enabled: false,
|
||||
|
||||
Reference in New Issue
Block a user