centralize accounts.srf loading

This commit is contained in:
Emil Lerch 2026-04-11 09:51:25 -07:00
parent 5ee2151a47
commit 518af59717
Signed by: lobo
GPG key ID: A7B62D657EF764F8
4 changed files with 21 additions and 29 deletions

View file

@ -65,15 +65,7 @@ pub fn run(allocator: std.mem.Allocator, svc: *zfin.DataService, file_path: []co
defer cm.deinit();
// Load account tax type metadata (optional)
const acct_path = std.fmt.allocPrint(allocator, "{s}accounts.srf", .{file_path[0..dir_end]}) catch return;
defer allocator.free(acct_path);
var acct_map_opt: ?zfin.analysis.AccountMap = null;
const acct_data = std.fs.cwd().readFileAlloc(allocator, acct_path, 1024 * 1024) catch null;
if (acct_data) |ad| {
defer allocator.free(ad);
acct_map_opt = zfin.analysis.parseAccountsFile(allocator, ad) catch null;
}
var acct_map_opt: ?zfin.analysis.AccountMap = svc.loadAccountMap(file_path);
defer if (acct_map_opt) |*am| am.deinit();
var result = zfin.analysis.analyzePortfolio(

View file

@ -1155,18 +1155,8 @@ pub fn run(allocator: std.mem.Allocator, svc: *zfin.DataService, args: []const [
defer portfolio.deinit();
// Load accounts.srf
const dir_end = if (std.mem.lastIndexOfScalar(u8, portfolio_path, std.fs.path.sep)) |idx| idx + 1 else 0;
const acct_path = std.fmt.allocPrint(allocator, "{s}accounts.srf", .{portfolio_path[0..dir_end]}) catch return;
defer allocator.free(acct_path);
const acct_data = std.fs.cwd().readFileAlloc(allocator, acct_path, 1024 * 1024) catch {
try cli.stderrPrint("Error: Cannot read accounts.srf (needed for account number mapping)\n");
return;
};
defer allocator.free(acct_data);
var account_map = analysis.parseAccountsFile(allocator, acct_data) catch {
try cli.stderrPrint("Error: Cannot parse accounts.srf\n");
var account_map = svc.loadAccountMap(portfolio_path) orelse {
try cli.stderrPrint("Error: Cannot read/parse accounts.srf (needed for account number mapping)\n");
return;
};
defer account_map.deinit();

View file

@ -20,6 +20,7 @@ const EtfProfile = @import("models/etf_profile.zig").EtfProfile;
const Config = @import("config.zig").Config;
const cache = @import("cache/store.zig");
const srf = @import("srf");
const analysis = @import("analytics/analysis.zig");
const TwelveData = @import("providers/twelvedata.zig").TwelveData;
const Polygon = @import("providers/polygon.zig").Polygon;
const Finnhub = @import("providers/finnhub.zig").Finnhub;
@ -1334,6 +1335,22 @@ pub const DataService = struct {
fn isMutualFund(symbol: []const u8) bool {
return symbol.len == 5 and symbol[4] == 'X';
}
// User config files
/// Load and parse accounts.srf from the same directory as the given portfolio path.
/// Returns null if the file doesn't exist or can't be parsed.
/// Caller owns the returned AccountMap and must call deinit().
pub fn loadAccountMap(self: *DataService, portfolio_path: []const u8) ?analysis.AccountMap {
const dir_end = if (std.mem.lastIndexOfScalar(u8, portfolio_path, std.fs.path.sep)) |idx| idx + 1 else 0;
const acct_path = std.fmt.allocPrint(self.allocator, "{s}accounts.srf", .{portfolio_path[0..dir_end]}) catch return null;
defer self.allocator.free(acct_path);
const data = std.fs.cwd().readFileAlloc(self.allocator, acct_path, 1024 * 1024) catch return null;
defer self.allocator.free(data);
return analysis.parseAccountsFile(self.allocator, data) catch null;
}
};
// Tests

View file

@ -827,14 +827,7 @@ pub const App = struct {
pub fn ensureAccountMap(self: *App) void {
if (self.account_map != null) return;
const ppath = self.portfolio_path orelse return;
const dir_end = if (std.mem.lastIndexOfScalar(u8, ppath, std.fs.path.sep)) |idx| idx + 1 else 0;
const acct_path = std.fmt.allocPrint(self.allocator, "{s}accounts.srf", .{ppath[0..dir_end]}) catch return;
defer self.allocator.free(acct_path);
if (std.fs.cwd().readFileAlloc(self.allocator, acct_path, 1024 * 1024)) |acct_data| {
defer self.allocator.free(acct_data);
self.account_map = zfin.analysis.parseAccountsFile(self.allocator, acct_data) catch null;
} else |_| {}
self.account_map = self.svc.loadAccountMap(ppath);
}
/// Set or clear the account filter. Owns the string via allocator.