Versie 0.2.0
This commit is contained in:
commit
e77d8fd373
495 files changed
+81026
No files matched your search
@@ -0,0 +1,88 @@
|
||||
// Generated, do not edit. sha256:8eb5f3330fcdfdbe9052fd4560a6ccd48f5f3aa7ef341ffd35df63e368fe3a71
|
||||
import * as db from '../db.js';
|
||||
import { toSearchName } from '../../shared/search-name.js';
|
||||
import { ENUMS } from '../../shared/config.js';
|
||||
import { assertEnum } from './_shared.js';
|
||||
import { fail } from '../../shared/app-error.js';
|
||||
import { trackDelete, trackUpdate } from './change-log.js';
|
||||
|
||||
export function hasMetalAssets() {
|
||||
return db.one(`SELECT 1 AS x FROM Asset WHERE kind = 'metal' LIMIT 1`) != null;
|
||||
}
|
||||
export function listMetalAssets() {
|
||||
return db.all(`SELECT * FROM Asset WHERE kind = 'metal' ORDER BY symbol`);
|
||||
}
|
||||
export function listMetalProducts() {
|
||||
return db.all(`SELECT mp.*, a.symbol AS asset_symbol, a.name AS asset_name
|
||||
FROM MetalProduct mp JOIN Asset a ON a.id = mp.assetId
|
||||
ORDER BY a.symbol, mp.form, mp.fineGrams`);
|
||||
}
|
||||
export function listMetalProductsForAsset(assetId) {
|
||||
return db.all(`SELECT * FROM MetalProduct WHERE assetId = ? ORDER BY form, fineGrams`, [assetId]);
|
||||
}
|
||||
function assertMetalProduct({ assetId, name, form, fineGrams }) {
|
||||
assertEnum('form', ENUMS.METAL_FORM, form);
|
||||
if (!Number.isInteger(assetId)) fail('metalProducts.assetRequired', null, 'Pick a valid metal asset.');
|
||||
if (!String(name || '').trim()) fail('metalProducts.nameRequired', null, 'The name is required.');
|
||||
if (!Number.isInteger(fineGrams) || fineGrams <= 0) fail('metalProducts.fineGramsPositive', null, 'The fine weight has to be greater than 0.');
|
||||
const a = db.one(`SELECT kind FROM Asset WHERE id = ?`, [assetId]);
|
||||
if (!a || a.kind !== 'metal') fail('metalProducts.notMetal', null, 'The chosen asset is not a metal.');
|
||||
}
|
||||
export async function createMetalProduct(p) {
|
||||
assertMetalProduct(p);
|
||||
db.run(`INSERT INTO MetalProduct (assetId, name, searchName, form, fineGrams) VALUES (?,?,?,?,?)`,
|
||||
[p.assetId, p.name.trim(), toSearchName(p.name), p.form, p.fineGrams]);
|
||||
const id = db.lastId();
|
||||
await db.persist();
|
||||
return id;
|
||||
}
|
||||
export async function updateMetalProduct(id, p) {
|
||||
assertMetalProduct(p);
|
||||
trackUpdate('MetalProduct', id, () =>
|
||||
db.run(`UPDATE MetalProduct SET assetId = ?, name = ?, searchName = ?, form = ?, fineGrams = ? WHERE id = ?`,
|
||||
[p.assetId, p.name.trim(), toSearchName(p.name), p.form, p.fineGrams, id]));
|
||||
await db.persist();
|
||||
}
|
||||
export async function deleteMetalProduct(id) {
|
||||
const used = db.one(`SELECT COUNT(*) AS n FROM Event WHERE productId = ?`, [id]).n;
|
||||
if (used > 0) fail('metalProducts.inUse', { n: used }, `Product is used by ${used} event(s); remove those first.`);
|
||||
trackDelete('MetalProduct', id, () => db.run(`DELETE FROM MetalProduct WHERE id = ?`, [id]));
|
||||
await db.persist();
|
||||
}
|
||||
|
||||
export function metalHoldings({ ownOnly = false } = {}) {
|
||||
return db.all(`
|
||||
SELECT mp.id, mp.name, mp.form, mp.fineGrams, mp.assetId,
|
||||
a.symbol AS asset_symbol, a.name AS asset_name,
|
||||
COALESCE(SUM(CASE
|
||||
WHEN e.type = 'buy' AND e.toIn THEN e.productCount
|
||||
WHEN e.type = 'sell' AND e.fromIn THEN -e.productCount
|
||||
-- Only a transfer between two ACCOUNTS of which one is own: a transfer out of the
|
||||
-- administration counts no pieces in either mode, so the two modes agree without a scope.
|
||||
WHEN e.type = 'transfer' AND ?1 = 1 AND e.toAccountId IS NOT NULL AND e.fromAccountId IS NOT NULL THEN
|
||||
(CASE WHEN e.toIn AND NOT e.fromIn THEN e.productCount ELSE 0 END)
|
||||
- (CASE WHEN e.fromIn AND NOT e.toIn THEN e.productCount ELSE 0 END)
|
||||
ELSE 0 END), 0) AS net_count,
|
||||
COALESCE(SUM(CASE WHEN e.type = 'buy' AND e.toIn THEN e.productCount ELSE 0 END), 0) AS buy_count,
|
||||
COALESCE(SUM(CASE WHEN e.type = 'buy' AND e.toIn AND e.priceOrigin IS NOT 'none' THEN 1 ELSE 0 END), 0) AS buy_events,
|
||||
COALESCE(SUM(CASE WHEN e.type = 'buy' AND e.toIn AND e.priceOrigin IS NOT 'none' THEN COALESCE(e.fiatFee,0) ELSE 0 END), 0) AS buy_premium,
|
||||
COALESCE(SUM(CASE WHEN e.type = 'buy' AND e.toIn AND e.priceOrigin IS NOT 'none' THEN e.amount ELSE 0 END), 0) AS buy_amount,
|
||||
COALESCE(SUM(CASE WHEN e.type = 'buy' AND e.toIn AND e.priceOrigin IS NOT 'none' THEN e.amount * COALESCE(e.fiatPrice,0) ELSE 0 END), 0) AS buy_spot_raw,
|
||||
COALESCE(SUM(CASE WHEN e.priceOrigin IS 'none' THEN
|
||||
(CASE WHEN e.type = 'buy' AND e.toIn THEN e.amount WHEN e.type = 'sell' AND e.fromIn THEN -e.amount ELSE 0 END)
|
||||
ELSE 0 END), 0) AS gift_amount
|
||||
FROM MetalProduct mp
|
||||
JOIN Asset a ON a.id = mp.assetId
|
||||
LEFT JOIN (
|
||||
SELECT Event.*,
|
||||
(?1 = 0 OR toAccount.wealthScope IS NULL) AS toIn,
|
||||
(?1 = 0 OR fromAccount.wealthScope IS NULL) AS fromIn
|
||||
FROM Event
|
||||
LEFT JOIN Account toAccount ON toAccount.id = Event.toAccountId
|
||||
LEFT JOIN Account fromAccount ON fromAccount.id = Event.fromAccountId
|
||||
WHERE Event.productCount IS NOT NULL
|
||||
) e ON e.productId = mp.id
|
||||
GROUP BY mp.id
|
||||
HAVING net_count > 0
|
||||
ORDER BY a.symbol, mp.form, mp.fineGrams`, [ownOnly ? 1 : 0]);
|
||||
}
|
||||
Reference in new issue
Block a user