Files
tradon/notes/accounting/excel_web_api/RefreshGLApi.ts
2026-05-29 08:07:09 +02:00

110 lines
4.5 KiB
TypeScript

/**
* GL Accounts refresh — Office Script for Excel Web.
*
* Setup:
* 1. Start the Python API: uvicorn main:app --port 8000
* 2. Expose via ngrok: ngrok http 8000
* 3. Paste the ngrok URL in API_BASE below.
* 4. In Excel Web: Automate tab > New Script > paste > Save > Run.
*
* Sheet layout (GL_Accounts_Client_Template.xlsx):
* Setup!B6 = Company Functions!C6 = get_account_base_amount
* Setup!B7 = Account Functions!C7 = get_account_real_base_amount
* Setup!B8 = Currency Functions!C8 = get_account_amount
* Setup!B9 = Date Functions!C9 = get_account_abbr
* Functions!C10 = get_account_name
* Functions!C11 = get_account_contact
* Functions!C12 = get_account_contact_code
* Functions!C13 = get_account_contact_name
*/
interface GlResults {
get_account_base_amount: number;
get_account_real_base_amount: number;
get_account_amount: number;
get_account_abbr: string;
get_account_name: string;
get_account_contact: string;
get_account_contact_code: string;
get_account_contact_name: string;
}
interface GlResponse {
results: GlResults;
errors: { [key: string]: string };
}
async function main(workbook: ExcelScript.Workbook): Promise<void> {
// ── CONFIG ─────────────────────────────────────────────────────────────────
const API_BASE = "https://obscure-boggle-sprig.ngrok-free.dev";
// ───────────────────────────────────────────────────────────────────────────
const setupSheet = workbook.getWorksheet("Setup");
const functionsSheet = workbook.getWorksheet("Functions");
if (!setupSheet || !functionsSheet) {
console.log("Error: 'Setup' or 'Functions' sheet not found.");
return;
}
const company: string = String(setupSheet.getRange("B6").getValue());
const account: string = String(setupSheet.getRange("B7").getValue());
const currency: string = String(setupSheet.getRange("B8").getValue());
const date: string = toIsoDate(setupSheet.getRange("B9").getValue());
// Mark as loading
for (let row = 6; row <= 13; row++) {
functionsSheet.getRange("C" + row).setValue("...");
}
const url = API_BASE + "/gl/all"
+ "?company=" + encodeURIComponent(company)
+ "&account=" + encodeURIComponent(account)
+ "&currency=" + encodeURIComponent(currency)
+ "&date=" + encodeURIComponent(date);
let data: GlResponse;
try {
const response = await fetch(url, {
headers: { "ngrok-skip-browser-warning": "true" }
});
if (!response.ok) {
throw new Error("HTTP " + response.status);
}
data = (await response.json()) as GlResponse;
} catch (err) {
console.log("API call failed: " + err);
for (let row = 6; row <= 13; row++) {
functionsSheet.getRange("C" + row).setValue("#API_ERROR");
}
return;
}
const r = data.results;
functionsSheet.getRange("C6").setValue(r.get_account_base_amount !== null ? r.get_account_base_amount : "");
functionsSheet.getRange("C7").setValue(r.get_account_real_base_amount !== null ? r.get_account_real_base_amount : "");
functionsSheet.getRange("C8").setValue(r.get_account_amount !== null ? r.get_account_amount : "");
functionsSheet.getRange("C9").setValue(r.get_account_abbr !== null ? r.get_account_abbr : "");
functionsSheet.getRange("C10").setValue(r.get_account_name !== null ? r.get_account_name : "");
functionsSheet.getRange("C11").setValue(r.get_account_contact !== null ? r.get_account_contact : "");
functionsSheet.getRange("C12").setValue(r.get_account_contact_code !== null ? r.get_account_contact_code : "");
functionsSheet.getRange("C13").setValue(r.get_account_contact_name !== null ? r.get_account_contact_name : "");
console.log("Refreshed: " + company + " / " + account + " / " + currency + " / " + date);
}
function toIsoDate(value: string | number | boolean): string {
if (typeof value === "number") {
// Excel date serial → YYYY-MM-DD
const d = new Date(Date.UTC(1899, 11, 30) + value * 86400000);
return d.toISOString().split("T")[0];
}
const s = String(value);
const d = new Date(s);
if (!isNaN(d.getTime())) {
return d.toISOString().split("T")[0];
}
return s;
}