feat(#10): Add per-ledger acquisitions view + ledger column
This commit is contained in:
+15
-19
@@ -814,10 +814,17 @@ paths:
|
|||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
- acquisition
|
- acquisition
|
||||||
summary: "Find acquisitions, optionally filtered by market type and consumption\
|
summary: "Find the caller's acquisitions, optionally filtered by ledger, market\
|
||||||
\ state"
|
\ type and consumption state"
|
||||||
operationId: findAllAcquisitions
|
operationId: findAllAcquisitions
|
||||||
parameters:
|
parameters:
|
||||||
|
- name: ledgerId
|
||||||
|
in: query
|
||||||
|
description: Only return acquisitions held in this ledger
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
- name: marketTypeId
|
- name: marketTypeId
|
||||||
in: query
|
in: query
|
||||||
description: Only return acquisitions of this market type
|
description: Only return acquisitions of this market type
|
||||||
@@ -848,10 +855,6 @@ components:
|
|||||||
description: Request to update the caller's rule book; replaces its mutable
|
description: Request to update the caller's rule book; replaces its mutable
|
||||||
fields.
|
fields.
|
||||||
properties:
|
properties:
|
||||||
usedForAcquisitions:
|
|
||||||
type: boolean
|
|
||||||
description: Whether this rule book is used to derive acquisitions.
|
|
||||||
example: true
|
|
||||||
bindings:
|
bindings:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
@@ -866,7 +869,6 @@ components:
|
|||||||
required:
|
required:
|
||||||
- bindings
|
- bindings
|
||||||
- script
|
- script
|
||||||
- usedForAcquisitions
|
|
||||||
RuleBookResponse:
|
RuleBookResponse:
|
||||||
type: object
|
type: object
|
||||||
description: "The caller's rule book: a script that classifies transactions,\
|
description: "The caller's rule book: a script that classifies transactions,\
|
||||||
@@ -877,10 +879,6 @@ components:
|
|||||||
format: uuid
|
format: uuid
|
||||||
description: Owning user identifier.
|
description: Owning user identifier.
|
||||||
example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
|
example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
|
||||||
usedForAcquisitions:
|
|
||||||
type: boolean
|
|
||||||
description: Whether this rule book is used to derive acquisitions.
|
|
||||||
example: true
|
|
||||||
bindings:
|
bindings:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
@@ -895,7 +893,6 @@ components:
|
|||||||
required:
|
required:
|
||||||
- bindings
|
- bindings
|
||||||
- script
|
- script
|
||||||
- usedForAcquisitions
|
|
||||||
- userId
|
- userId
|
||||||
UpdateMainLedgerRequest:
|
UpdateMainLedgerRequest:
|
||||||
type: object
|
type: object
|
||||||
@@ -1686,6 +1683,11 @@ components:
|
|||||||
format: uuid
|
format: uuid
|
||||||
description: Unique acquisition identifier.
|
description: Unique acquisition identifier.
|
||||||
example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
|
example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
|
||||||
|
ledgerId:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
description: Ledger the acquisition is held in.
|
||||||
|
example: 3fa85f64-5717-4562-b3fc-2c963f66afa6
|
||||||
source:
|
source:
|
||||||
$ref: "#/components/schemas/ActivitySourceResponse"
|
$ref: "#/components/schemas/ActivitySourceResponse"
|
||||||
description: "Where the acquisition came from: a character, a corporation,\
|
description: "Where the acquisition came from: a character, a corporation,\
|
||||||
@@ -1695,12 +1697,6 @@ components:
|
|||||||
format: int64
|
format: int64
|
||||||
description: EVE market type (item) id that was acquired.
|
description: EVE market type (item) id that was acquired.
|
||||||
example: 34
|
example: 34
|
||||||
origin:
|
|
||||||
type: string
|
|
||||||
description: How the item entered the inventory.
|
|
||||||
enum:
|
|
||||||
- BOUGHT
|
|
||||||
- MANUAL
|
|
||||||
datetime:
|
datetime:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
@@ -1723,8 +1719,8 @@ components:
|
|||||||
required:
|
required:
|
||||||
- acquisitionId
|
- acquisitionId
|
||||||
- datetime
|
- datetime
|
||||||
|
- ledgerId
|
||||||
- marketTypeId
|
- marketTypeId
|
||||||
- origin
|
|
||||||
- quantity
|
- quantity
|
||||||
- remaining
|
- remaining
|
||||||
- source
|
- source
|
||||||
|
|||||||
+23
-31
@@ -31,6 +31,10 @@ export interface AcquisitionResponse {
|
|||||||
* Unique acquisition identifier.
|
* Unique acquisition identifier.
|
||||||
*/
|
*/
|
||||||
'acquisitionId': string;
|
'acquisitionId': string;
|
||||||
|
/**
|
||||||
|
* Ledger the acquisition is held in.
|
||||||
|
*/
|
||||||
|
'ledgerId': string;
|
||||||
/**
|
/**
|
||||||
* Where the acquisition came from: a character, a corporation, or nothing.
|
* Where the acquisition came from: a character, a corporation, or nothing.
|
||||||
*/
|
*/
|
||||||
@@ -39,10 +43,6 @@ export interface AcquisitionResponse {
|
|||||||
* EVE market type (item) id that was acquired.
|
* EVE market type (item) id that was acquired.
|
||||||
*/
|
*/
|
||||||
'marketTypeId': number;
|
'marketTypeId': number;
|
||||||
/**
|
|
||||||
* How the item entered the inventory.
|
|
||||||
*/
|
|
||||||
'origin': AcquisitionResponseOriginEnum;
|
|
||||||
/**
|
/**
|
||||||
* When the acquisition occurred.
|
* When the acquisition occurred.
|
||||||
*/
|
*/
|
||||||
@@ -60,14 +60,6 @@ export interface AcquisitionResponse {
|
|||||||
*/
|
*/
|
||||||
'unitCost': number;
|
'unitCost': number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AcquisitionResponseOriginEnum = {
|
|
||||||
Bought: 'BOUGHT',
|
|
||||||
Manual: 'MANUAL',
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export type AcquisitionResponseOriginEnum = typeof AcquisitionResponseOriginEnum[keyof typeof AcquisitionResponseOriginEnum];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Where an activity or transaction came from: a character, a corporation wallet, or nothing (a manual entry).
|
* Where an activity or transaction came from: a character, a corporation wallet, or nothing (a manual entry).
|
||||||
*/
|
*/
|
||||||
@@ -612,10 +604,6 @@ export interface RuleBookResponse {
|
|||||||
* Owning user identifier.
|
* Owning user identifier.
|
||||||
*/
|
*/
|
||||||
'userId': string;
|
'userId': string;
|
||||||
/**
|
|
||||||
* Whether this rule book is used to derive acquisitions.
|
|
||||||
*/
|
|
||||||
'usedForAcquisitions': boolean;
|
|
||||||
/**
|
/**
|
||||||
* Ledger references the script writes to, each bound to one of the user\'s ledgers.
|
* Ledger references the script writes to, each bound to one of the user\'s ledgers.
|
||||||
*/
|
*/
|
||||||
@@ -682,10 +670,6 @@ export interface UpdateMainLedgerRequest {
|
|||||||
* Request to update the caller\'s rule book; replaces its mutable fields.
|
* Request to update the caller\'s rule book; replaces its mutable fields.
|
||||||
*/
|
*/
|
||||||
export interface UpdateRuleBookRequest {
|
export interface UpdateRuleBookRequest {
|
||||||
/**
|
|
||||||
* Whether this rule book is used to derive acquisitions.
|
|
||||||
*/
|
|
||||||
'usedForAcquisitions': boolean;
|
|
||||||
/**
|
/**
|
||||||
* Ledger references the script writes to, each bound to one of the user\'s ledgers.
|
* Ledger references the script writes to, each bound to one of the user\'s ledgers.
|
||||||
*/
|
*/
|
||||||
@@ -703,13 +687,14 @@ export const AcquisitionApiAxiosParamCreator = function (configuration?: Configu
|
|||||||
return {
|
return {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @summary Find acquisitions, optionally filtered by market type and consumption state
|
* @summary Find the caller\'s acquisitions, optionally filtered by ledger, market type and consumption state
|
||||||
|
* @param {string} [ledgerId] Only return acquisitions held in this ledger
|
||||||
* @param {number} [marketTypeId] Only return acquisitions of this market type
|
* @param {number} [marketTypeId] Only return acquisitions of this market type
|
||||||
* @param {boolean} [includeConsumed] Include fully consumed acquisitions (no remaining stock)
|
* @param {boolean} [includeConsumed] Include fully consumed acquisitions (no remaining stock)
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
*/
|
*/
|
||||||
findAllAcquisitions: async (marketTypeId?: number, includeConsumed?: boolean, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
|
findAllAcquisitions: async (ledgerId?: string, marketTypeId?: number, includeConsumed?: boolean, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||||
const localVarPath = `/acquisitions`;
|
const localVarPath = `/acquisitions`;
|
||||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||||
@@ -722,6 +707,10 @@ export const AcquisitionApiAxiosParamCreator = function (configuration?: Configu
|
|||||||
const localVarHeaderParameter = {} as any;
|
const localVarHeaderParameter = {} as any;
|
||||||
const localVarQueryParameter = {} as any;
|
const localVarQueryParameter = {} as any;
|
||||||
|
|
||||||
|
if (ledgerId !== undefined) {
|
||||||
|
localVarQueryParameter['ledgerId'] = ledgerId;
|
||||||
|
}
|
||||||
|
|
||||||
if (marketTypeId !== undefined) {
|
if (marketTypeId !== undefined) {
|
||||||
localVarQueryParameter['marketTypeId'] = marketTypeId;
|
localVarQueryParameter['marketTypeId'] = marketTypeId;
|
||||||
}
|
}
|
||||||
@@ -752,14 +741,15 @@ export const AcquisitionApiFp = function(configuration?: Configuration) {
|
|||||||
return {
|
return {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @summary Find acquisitions, optionally filtered by market type and consumption state
|
* @summary Find the caller\'s acquisitions, optionally filtered by ledger, market type and consumption state
|
||||||
|
* @param {string} [ledgerId] Only return acquisitions held in this ledger
|
||||||
* @param {number} [marketTypeId] Only return acquisitions of this market type
|
* @param {number} [marketTypeId] Only return acquisitions of this market type
|
||||||
* @param {boolean} [includeConsumed] Include fully consumed acquisitions (no remaining stock)
|
* @param {boolean} [includeConsumed] Include fully consumed acquisitions (no remaining stock)
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
*/
|
*/
|
||||||
async findAllAcquisitions(marketTypeId?: number, includeConsumed?: boolean, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<AcquisitionResponse>>> {
|
async findAllAcquisitions(ledgerId?: string, marketTypeId?: number, includeConsumed?: boolean, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<AcquisitionResponse>>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.findAllAcquisitions(marketTypeId, includeConsumed, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.findAllAcquisitions(ledgerId, marketTypeId, includeConsumed, options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['AcquisitionApi.findAllAcquisitions']?.[localVarOperationServerIndex]?.url;
|
const localVarOperationServerBasePath = operationServerMap['AcquisitionApi.findAllAcquisitions']?.[localVarOperationServerIndex]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
||||||
@@ -775,14 +765,15 @@ export const AcquisitionApiFactory = function (configuration?: Configuration, ba
|
|||||||
return {
|
return {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @summary Find acquisitions, optionally filtered by market type and consumption state
|
* @summary Find the caller\'s acquisitions, optionally filtered by ledger, market type and consumption state
|
||||||
|
* @param {string} [ledgerId] Only return acquisitions held in this ledger
|
||||||
* @param {number} [marketTypeId] Only return acquisitions of this market type
|
* @param {number} [marketTypeId] Only return acquisitions of this market type
|
||||||
* @param {boolean} [includeConsumed] Include fully consumed acquisitions (no remaining stock)
|
* @param {boolean} [includeConsumed] Include fully consumed acquisitions (no remaining stock)
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
*/
|
*/
|
||||||
findAllAcquisitions(marketTypeId?: number, includeConsumed?: boolean, options?: RawAxiosRequestConfig): AxiosPromise<Array<AcquisitionResponse>> {
|
findAllAcquisitions(ledgerId?: string, marketTypeId?: number, includeConsumed?: boolean, options?: RawAxiosRequestConfig): AxiosPromise<Array<AcquisitionResponse>> {
|
||||||
return localVarFp.findAllAcquisitions(marketTypeId, includeConsumed, options).then((request) => request(axios, basePath));
|
return localVarFp.findAllAcquisitions(ledgerId, marketTypeId, includeConsumed, options).then((request) => request(axios, basePath));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -793,14 +784,15 @@ export const AcquisitionApiFactory = function (configuration?: Configuration, ba
|
|||||||
export class AcquisitionApi extends BaseAPI {
|
export class AcquisitionApi extends BaseAPI {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @summary Find acquisitions, optionally filtered by market type and consumption state
|
* @summary Find the caller\'s acquisitions, optionally filtered by ledger, market type and consumption state
|
||||||
|
* @param {string} [ledgerId] Only return acquisitions held in this ledger
|
||||||
* @param {number} [marketTypeId] Only return acquisitions of this market type
|
* @param {number} [marketTypeId] Only return acquisitions of this market type
|
||||||
* @param {boolean} [includeConsumed] Include fully consumed acquisitions (no remaining stock)
|
* @param {boolean} [includeConsumed] Include fully consumed acquisitions (no remaining stock)
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
*/
|
*/
|
||||||
public findAllAcquisitions(marketTypeId?: number, includeConsumed?: boolean, options?: RawAxiosRequestConfig) {
|
public findAllAcquisitions(ledgerId?: string, marketTypeId?: number, includeConsumed?: boolean, options?: RawAxiosRequestConfig) {
|
||||||
return AcquisitionApiFp(this.configuration).findAllAcquisitions(marketTypeId, includeConsumed, options).then((request) => request(this.axios, this.basePath));
|
return AcquisitionApiFp(this.configuration).findAllAcquisitions(ledgerId, marketTypeId, includeConsumed, options).then((request) => request(this.axios, this.basePath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
import {isCombined, Ledger, systemLedger} from "@/ledger/ledger.ts";
|
import {isCombined, isMain, Ledger, systemLedger} from "@/ledger/ledger.ts";
|
||||||
import {FolderOpenIcon} from '@heroicons/vue/24/outline';
|
import {DocumentIcon, FolderOpenIcon} from '@heroicons/vue/24/outline';
|
||||||
import {RouterLink} from "vue-router";
|
import {RouterLink} from "vue-router";
|
||||||
import {routeNames} from "@/routes";
|
import {routeNames} from "@/routes";
|
||||||
|
|
||||||
@@ -15,7 +15,8 @@ const props = defineProps<Props>();
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<FolderOpenIcon v-if="isCombined(ledger)" class="w-4 me-1" />
|
<DocumentIcon v-if="isMain(ledger)" class="w-4 me-1" />
|
||||||
|
<FolderOpenIcon v-else-if="isCombined(ledger)" class="w-4 me-1" />
|
||||||
<div v-else class="w-4 me-1"/>
|
<div v-else class="w-4 me-1"/>
|
||||||
<RouterLink v-if="link" :to="{name: routeNames.viewLedger, params: {ledgerId: ledger.ledgerId}}">{{ ledger.name }}</RouterLink>
|
<RouterLink v-if="link" :to="{name: routeNames.viewLedger, params: {ledgerId: ledger.ledgerId}}">{{ ledger.name }}</RouterLink>
|
||||||
<span v-else :class="{'system-ledger': ledger === systemLedger}">{{ ledger.name }}</span>
|
<span v-else :class="{'system-ledger': ledger === systemLedger}">{{ ledger.name }}</span>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {computed, ref} from 'vue';
|
|||||||
import {AcquiredType} from './AcquiredType';
|
import {AcquiredType} from './AcquiredType';
|
||||||
import AcquisitionQuartilesTooltip from './AcquisitionQuartilesTooltip.vue';
|
import AcquisitionQuartilesTooltip from './AcquisitionQuartilesTooltip.vue';
|
||||||
import {formatEveDate, formatIsk, percentFormater} from "@/formaters.ts";
|
import {formatEveDate, formatIsk, percentFormater} from "@/formaters.ts";
|
||||||
|
import {Ledger, LedgerLabel, useLedgersStore} from "@/ledger";
|
||||||
|
|
||||||
type Result = {
|
type Result = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -20,6 +21,8 @@ type Result = {
|
|||||||
precentProfit: number;
|
precentProfit: number;
|
||||||
iskProfit: number;
|
iskProfit: number;
|
||||||
date: Date;
|
date: Date;
|
||||||
|
ledger?: Ledger;
|
||||||
|
ledgerName: string;
|
||||||
acquisitions: AcquiredType[];
|
acquisitions: AcquiredType[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,15 +49,22 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
defineEmits<Emits>();
|
defineEmits<Emits>();
|
||||||
|
|
||||||
const columnsToIgnore = computed(() => {
|
const columnsToIgnore = computed(() => {
|
||||||
const ic = typeof props.ignoredColums === 'string' ? [props.ignoredColums] : props.ignoredColums;
|
const ignoredColums = typeof props.ignoredColums === 'string' ? [props.ignoredColums] : [...props.ignoredColums];
|
||||||
|
|
||||||
if (props.infoOnly && !ic.includes('buttons')) {
|
if (props.infoOnly && !ignoredColums.includes('buttons')) {
|
||||||
return [...ic, 'buttons'];
|
ignoredColums.push('buttons');
|
||||||
}
|
}
|
||||||
return ic;
|
if (!props.showAll && !ignoredColums.includes('ledger')) {
|
||||||
|
ignoredColums.push('ledger');
|
||||||
|
}
|
||||||
|
if (ignoredColums.includes('ledger')) {
|
||||||
|
ignoredColums.push('ledgerName');
|
||||||
|
}
|
||||||
|
return ignoredColums;
|
||||||
});
|
});
|
||||||
|
|
||||||
const marketTaxStore = useMarketTaxStore();
|
const marketTaxStore = useMarketTaxStore();
|
||||||
|
const ledgersStore = useLedgersStore();
|
||||||
|
|
||||||
const threshold = useStorage('market-acquisition-threshold', 10);
|
const threshold = useStorage('market-acquisition-threshold', 10);
|
||||||
const filter = ref("");
|
const filter = ref("");
|
||||||
@@ -77,6 +87,8 @@ const { sortedArray, headerProps, showColumn } = useSort<Result>(computed(() =>
|
|||||||
precentProfit,
|
precentProfit,
|
||||||
iskProfit: r.price * precentProfit * r.remaining,
|
iskProfit: r.price * precentProfit * r.remaining,
|
||||||
date: r.date,
|
date: r.date,
|
||||||
|
ledger: ledgersStore.findById(r.ledgerId),
|
||||||
|
ledgerName: ledgersStore.findById(r.ledgerId)?.name ?? '',
|
||||||
acquisitions: [r]
|
acquisitions: [r]
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -109,6 +121,7 @@ const { sortedArray, headerProps, showColumn } = useSort<Result>(computed(() =>
|
|||||||
precentProfit,
|
precentProfit,
|
||||||
iskProfit: price * precentProfit * totalRemaining,
|
iskProfit: price * precentProfit * totalRemaining,
|
||||||
date: first.date,
|
date: first.date,
|
||||||
|
ledgerName: '',
|
||||||
acquisitions: group
|
acquisitions: group
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -176,6 +189,7 @@ const total = computed(() => {
|
|||||||
<SortableHeader v-bind="headerProps" sortKey="name">Item</SortableHeader>
|
<SortableHeader v-bind="headerProps" sortKey="name">Item</SortableHeader>
|
||||||
<SortableHeader v-bind="headerProps" sortKey="buy">Buy</SortableHeader>
|
<SortableHeader v-bind="headerProps" sortKey="buy">Buy</SortableHeader>
|
||||||
<SortableHeader v-bind="headerProps" sortKey="sell">Sell</SortableHeader>
|
<SortableHeader v-bind="headerProps" sortKey="sell">Sell</SortableHeader>
|
||||||
|
<SortableHeader v-bind="headerProps" sortKey="ledgerName">Ledger</SortableHeader>
|
||||||
<SortableHeader v-bind="headerProps" sortKey="date">Bought at</SortableHeader>
|
<SortableHeader v-bind="headerProps" sortKey="date">Bought at</SortableHeader>
|
||||||
<SortableHeader v-bind="headerProps" sortKey="price">Bought Price</SortableHeader>
|
<SortableHeader v-bind="headerProps" sortKey="price">Bought Price</SortableHeader>
|
||||||
<SortableHeader v-bind="headerProps" sortKey="remaining">Remaining Amount</SortableHeader>
|
<SortableHeader v-bind="headerProps" sortKey="remaining">Remaining Amount</SortableHeader>
|
||||||
@@ -194,6 +208,9 @@ const total = computed(() => {
|
|||||||
</td>
|
</td>
|
||||||
<td v-if="showColumn('buy')" class="text-right">{{ formatIsk(r.data.buy) }}</td>
|
<td v-if="showColumn('buy')" class="text-right">{{ formatIsk(r.data.buy) }}</td>
|
||||||
<td v-if="showColumn('sell')" class="text-right">{{ formatIsk(r.data.sell) }}</td>
|
<td v-if="showColumn('sell')" class="text-right">{{ formatIsk(r.data.sell) }}</td>
|
||||||
|
<td v-if="showColumn('ledger')">
|
||||||
|
<LedgerLabel v-if="r.data.ledger" :ledger="r.data.ledger" link />
|
||||||
|
</td>
|
||||||
<td v-if="showColumn('date')" class="text-right">{{ formatEveDate(r.data.date) }}</td>
|
<td v-if="showColumn('date')" class="text-right">{{ formatEveDate(r.data.date) }}</td>
|
||||||
<td v-if="showColumn('price')" class="text-right">{{ formatIsk(r.data.price) }}</td>
|
<td v-if="showColumn('price')" class="text-right">{{ formatIsk(r.data.price) }}</td>
|
||||||
<td v-if="showColumn('remaining')" class="text-right">{{ r.data.remaining }}/{{ r.data.quantity }}</td>
|
<td v-if="showColumn('remaining')" class="text-right">{{ r.data.remaining }}/{{ r.data.quantity }}</td>
|
||||||
@@ -214,9 +231,12 @@ const total = computed(() => {
|
|||||||
<td v-if="showColumn('sell')">
|
<td v-if="showColumn('sell')">
|
||||||
<template v-if="!showColumn('name') && !showColumn('buy')">Total</template>
|
<template v-if="!showColumn('name') && !showColumn('buy')">Total</template>
|
||||||
</td>
|
</td>
|
||||||
<td v-if="showColumn('date')">
|
<td v-if="showColumn('ledger')">
|
||||||
<template v-if="!showColumn('name') && !showColumn('buy') && !showColumn('sell')">Total</template>
|
<template v-if="!showColumn('name') && !showColumn('buy') && !showColumn('sell')">Total</template>
|
||||||
</td>
|
</td>
|
||||||
|
<td v-if="showColumn('date')">
|
||||||
|
<template v-if="!showColumn('name') && !showColumn('buy') && !showColumn('sell') && !showColumn('ledger')">Total</template>
|
||||||
|
</td>
|
||||||
<td v-if="showColumn('price')" class="text-right">
|
<td v-if="showColumn('price')" class="text-right">
|
||||||
<template v-if="total.sameItem">
|
<template v-if="total.sameItem">
|
||||||
{{ formatIsk(total.price) }}
|
{{ formatIsk(total.price) }}
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {getMarketTypes, MarketTypePrice, useApraisalStore} from "@/market";
|
||||||
|
import {ref, watch} from 'vue';
|
||||||
|
import {AcquiredType} from './AcquiredType';
|
||||||
|
import {RawAcquiredType} from './acquisition';
|
||||||
|
import AcquisitionResultTable from './AcquisitionResultTable.vue';
|
||||||
|
import BuyModal from './BuyModal.vue';
|
||||||
|
import SellModal from './SellModal.vue';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
items: RawAcquiredType[];
|
||||||
|
ignoredColums?: string[] | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const buyModal = ref<typeof BuyModal>();
|
||||||
|
const sellModal = ref<typeof SellModal>();
|
||||||
|
|
||||||
|
const apraisalStore = useApraisalStore();
|
||||||
|
const enriched = ref<AcquiredType[]>([]);
|
||||||
|
|
||||||
|
watch(() => props.items, async itms => {
|
||||||
|
if (itms.length === 0) {
|
||||||
|
enriched.value = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const types = await getMarketTypes([...new Set(itms.map(i => i.type))]);
|
||||||
|
const prices = await apraisalStore.getPrices(types);
|
||||||
|
|
||||||
|
enriched.value = itms.map(i => {
|
||||||
|
const price = prices.find(p => p.type.id === i.type) as MarketTypePrice;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...i,
|
||||||
|
type: price.type,
|
||||||
|
buy: price.buy,
|
||||||
|
sell: price.sell
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}, {immediate: true});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<template v-if="enriched.length > 0">
|
||||||
|
<AcquisitionResultTable :items="enriched" :ignoredColums="ignoredColums" @buy="(types, price, buy, sell) => buyModal?.open(types[0].type, { 'Price': price, 'Buy': buy, 'Sell': sell })" @sell="types => sellModal?.open(types)" />
|
||||||
|
<BuyModal ref="buyModal" />
|
||||||
|
<SellModal ref="sellModal" />
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
@@ -7,6 +7,7 @@ export type AcquiredTypeSource = 'bo' | 'so' | 'prod' | 'misc';
|
|||||||
|
|
||||||
export type RawAcquiredType = {
|
export type RawAcquiredType = {
|
||||||
id: string;
|
id: string;
|
||||||
|
ledgerId: string;
|
||||||
type: number;
|
type: number;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
remaining: number;
|
remaining: number;
|
||||||
@@ -15,8 +16,9 @@ export type RawAcquiredType = {
|
|||||||
source: ActivitySourceResponse;
|
source: ActivitySourceResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
const toAcquiredType = (a: AcquisitionResponse): RawAcquiredType => ({
|
export const toAcquiredType = (a: AcquisitionResponse): RawAcquiredType => ({
|
||||||
id: a.acquisitionId,
|
id: a.acquisitionId,
|
||||||
|
ledgerId: a.ledgerId,
|
||||||
type: a.marketTypeId,
|
type: a.marketTypeId,
|
||||||
quantity: a.quantity,
|
quantity: a.quantity,
|
||||||
remaining: a.remaining,
|
remaining: a.remaining,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ export * from './AcquiredType';
|
|||||||
export * from './acquisition';
|
export * from './acquisition';
|
||||||
|
|
||||||
export { default as AcquisitionResultTable } from './AcquisitionResultTable.vue';
|
export { default as AcquisitionResultTable } from './AcquisitionResultTable.vue';
|
||||||
|
export { default as AcquisitionsPanel } from './AcquisitionsPanel.vue';
|
||||||
export { default as BuyModal } from './BuyModal.vue';
|
export { default as BuyModal } from './BuyModal.vue';
|
||||||
export { default as SellModal } from './SellModal.vue';
|
export { default as SellModal } from './SellModal.vue';
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {RouterLink, RouterView} from 'vue-router';
|
|||||||
import {useLedgerParam} from "@/ledger";
|
import {useLedgerParam} from "@/ledger";
|
||||||
import {routeNames} from "@/routes.ts";
|
import {routeNames} from "@/routes.ts";
|
||||||
|
|
||||||
const {ledgerId, ledger} = useLedgerParam();
|
const {ledger} = useLedgerParam();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -16,6 +16,9 @@ const {ledgerId, ledger} = useLedgerParam();
|
|||||||
<RouterLink :to="{name: routeNames.listLedgerTransactions}" class="tab">
|
<RouterLink :to="{name: routeNames.listLedgerTransactions}" class="tab">
|
||||||
<span>Transactions</span>
|
<span>Transactions</span>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
|
<RouterLink :to="{name: routeNames.listLedgerAcquisitions}" class="tab">
|
||||||
|
<span>Acquisitions</span>
|
||||||
|
</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
<RouterView />
|
<RouterView />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {AcquisitionsPanel, toAcquiredType} from '@/market/acquisition';
|
||||||
|
import {useLedgerParam} from "@/ledger";
|
||||||
|
import {acquisitionApi} from "@/mammon";
|
||||||
|
import {computedAsync} from "@vueuse/core";
|
||||||
|
|
||||||
|
const {ledgerId} = useLedgerParam();
|
||||||
|
|
||||||
|
const items = computedAsync(async () => {
|
||||||
|
if (!ledgerId.value) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const {data} = await acquisitionApi.findAllAcquisitions(ledgerId.value);
|
||||||
|
|
||||||
|
return data.map(toAcquiredType).filter(a => a.remaining > 0);
|
||||||
|
}, []);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="mt-4">
|
||||||
|
<AcquisitionsPanel :items="items" :ignoredColums="['date', 'ledger']" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -1,42 +1,15 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {getMarketTypes, MarketTypePrice, useApraisalStore} from "@/market";
|
import {AcquisitionsPanel, useAcquiredTypesStore} from '@/market/acquisition';
|
||||||
import {AcquiredType, AcquisitionResultTable, BuyModal, SellModal, useAcquiredTypesStore} from '@/market/acquisition';
|
|
||||||
import {ref, watch} from 'vue';
|
|
||||||
import {ArrowPathIcon} from '@heroicons/vue/24/outline';
|
import {ArrowPathIcon} from '@heroicons/vue/24/outline';
|
||||||
import {useAutoRefresh} from '@/composables';
|
import {useAutoRefresh} from '@/composables';
|
||||||
|
|
||||||
const buyModal = ref<typeof BuyModal>();
|
|
||||||
const sellModal = ref<typeof SellModal>();
|
|
||||||
|
|
||||||
const apraisalStore = useApraisalStore();
|
|
||||||
const acquiredTypesStore = useAcquiredTypesStore();
|
const acquiredTypesStore = useAcquiredTypesStore();
|
||||||
const items = ref<AcquiredType[]>([]);
|
|
||||||
|
|
||||||
const refresh = async () => {
|
const refresh = async () => {
|
||||||
await acquiredTypesStore.refresh();
|
await acquiredTypesStore.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
const {active: autoRefresh, toggle: toggleAutoRefresh} = useAutoRefresh(refresh, 5 * 60 * 1000);
|
const {active: autoRefresh, toggle: toggleAutoRefresh} = useAutoRefresh(refresh, 5 * 60 * 1000);
|
||||||
|
|
||||||
watch(() => acquiredTypesStore.acquiredTypes, async itms => {
|
|
||||||
if (itms.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const prices = await apraisalStore.getPrices(await getMarketTypes([...new Set(itms.map(i => i.type))]));
|
|
||||||
|
|
||||||
items.value = itms.map(i => {
|
|
||||||
const price = prices.find(p => p.type.id === i.type) as MarketTypePrice;
|
|
||||||
|
|
||||||
return {
|
|
||||||
...i,
|
|
||||||
type: price.type,
|
|
||||||
buy: price.buy,
|
|
||||||
sell: price.sell
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}, { immediate: true })
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -49,10 +22,6 @@ watch(() => acquiredTypesStore.acquiredTypes, async itms => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="items.length > 0">
|
<AcquisitionsPanel :items="acquiredTypesStore.acquiredTypes" ignoredColums="date" />
|
||||||
<AcquisitionResultTable :items="items" @buy="(types, price, buy, sell) => buyModal?.open(types[0].type, { 'Price': price, 'Buy': buy, 'Sell': sell })" @sell="types => sellModal?.open(types)" ignoredColums="date" />
|
|
||||||
<BuyModal ref="buyModal" />
|
|
||||||
<SellModal ref="sellModal" />
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -40,9 +40,10 @@ const result = computedAsync(async () => {
|
|||||||
const acquisitions = computedAsync(async () => {
|
const acquisitions = computedAsync(async () => {
|
||||||
const p = price.value;
|
const p = price.value;
|
||||||
|
|
||||||
return !p ? [] : (await acquisitionApi.findAllAcquisitions(item.value?.id, true)).data
|
return !p ? [] : (await acquisitionApi.findAllAcquisitions(undefined, item.value?.id, true)).data
|
||||||
.map(a => ({
|
.map(a => ({
|
||||||
id: a.acquisitionId,
|
id: a.acquisitionId,
|
||||||
|
ledgerId: a.ledgerId,
|
||||||
quantity: a.quantity,
|
quantity: a.quantity,
|
||||||
remaining: a.remaining,
|
remaining: a.remaining,
|
||||||
price: a.unitCost,
|
price: a.unitCost,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import {useEventListener} from "@vueuse/core";
|
|||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import {ScriptEditor, useRuleBookStore} from "@/rules";
|
import {ScriptEditor, useRuleBookStore} from "@/rules";
|
||||||
import {PlusIcon, TrashIcon} from "@heroicons/vue/24/outline";
|
import {PlusIcon, TrashIcon} from "@heroicons/vue/24/outline";
|
||||||
import {SliderCheckbox} from "@/components";
|
|
||||||
import {isMain, Ledger, LedgerSelect, systemLedger, useLedgersStore} from "@/ledger";
|
import {isMain, Ledger, LedgerSelect, systemLedger, useLedgersStore} from "@/ledger";
|
||||||
|
|
||||||
type Binding = { ref: string; ledger: Ledger };
|
type Binding = { ref: string; ledger: Ledger };
|
||||||
@@ -14,7 +13,6 @@ const ledgersStore = useLedgersStore();
|
|||||||
|
|
||||||
const ledgersToUse = computed(() => [systemLedger, ...ledgersStore.ledgers.filter(isMain)]);
|
const ledgersToUse = computed(() => [systemLedger, ...ledgersStore.ledgers.filter(isMain)]);
|
||||||
|
|
||||||
const usedForAcquisitions = ref<boolean>(false);
|
|
||||||
const bindings = ref<Binding[]>([]);
|
const bindings = ref<Binding[]>([]);
|
||||||
const script = ref<string>('');
|
const script = ref<string>('');
|
||||||
|
|
||||||
@@ -23,7 +21,6 @@ const ledgerRefs = computed<string[]>(() => bindings.value.map(b => b.ref));
|
|||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
const ruleBook = ruleBookStore.ruleBook;
|
const ruleBook = ruleBookStore.ruleBook;
|
||||||
|
|
||||||
usedForAcquisitions.value = ruleBook?.usedForAcquisitions ?? false;
|
|
||||||
script.value = ruleBook?.script ?? '';
|
script.value = ruleBook?.script ?? '';
|
||||||
bindings.value = Object.entries(ruleBook?.bindings ?? {})
|
bindings.value = Object.entries(ruleBook?.bindings ?? {})
|
||||||
.map(([ref, id]) => ({ref, ledger: ledgersToUse.value.find(l => l.ledgerId === id) ?? systemLedger}));
|
.map(([ref, id]) => ({ref, ledger: ledgersToUse.value.find(l => l.ledgerId === id) ?? systemLedger}));
|
||||||
@@ -39,7 +36,6 @@ const removeBinding = (index: number) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const save = () => ruleBookStore.update({
|
const save = () => ruleBookStore.update({
|
||||||
usedForAcquisitions: usedForAcquisitions.value,
|
|
||||||
bindings: Object.fromEntries(
|
bindings: Object.fromEntries(
|
||||||
bindings.value
|
bindings.value
|
||||||
.filter(b => b.ref)
|
.filter(b => b.ref)
|
||||||
@@ -59,12 +55,6 @@ useEventListener(window, 'keydown', (event: KeyboardEvent) => {
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col mb-2 mt-4 h-[calc(100vh-4.5rem)]">
|
<div class="flex flex-col mb-2 mt-4 h-[calc(100vh-4.5rem)]">
|
||||||
<div class="flex flex-col grow min-h-0">
|
<div class="flex flex-col grow min-h-0">
|
||||||
<div class="flex grow border-b-1">
|
|
||||||
<label class="flex items-center mb-2">
|
|
||||||
<SliderCheckbox class="me-2" v-model="usedForAcquisitions" />
|
|
||||||
Used for acquisitions
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="border-b-1">
|
<div class="border-b-1">
|
||||||
Ledger Bindings:
|
Ledger Bindings:
|
||||||
<div class="flex flex-wrap items-center mt-2">
|
<div class="flex flex-wrap items-center mt-2">
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export const routeNames = {
|
|||||||
viewLedger: 'view-ledger',
|
viewLedger: 'view-ledger',
|
||||||
viewLedgerBalance: 'view-ledger-balance',
|
viewLedgerBalance: 'view-ledger-balance',
|
||||||
listLedgerTransactions: 'list-ledger-transactions',
|
listLedgerTransactions: 'list-ledger-transactions',
|
||||||
|
listLedgerAcquisitions: 'list-ledger-acquisitions',
|
||||||
editRuleBook: 'edit-rule-book',
|
editRuleBook: 'edit-rule-book',
|
||||||
marketTypes: 'market-types',
|
marketTypes: 'market-types',
|
||||||
about: 'about',
|
about: 'about',
|
||||||
@@ -27,6 +28,7 @@ export const routes: RouteRecordRaw[] = [
|
|||||||
{path: '', name: routeNames.viewLedger, redirect: {name: routeNames.viewLedgerBalance}},
|
{path: '', name: routeNames.viewLedger, redirect: {name: routeNames.viewLedgerBalance}},
|
||||||
{path: 'balance', name: routeNames.viewLedgerBalance, component: () => import('@/pages/ledger/ViewLedgerBalance.vue')},
|
{path: 'balance', name: routeNames.viewLedgerBalance, component: () => import('@/pages/ledger/ViewLedgerBalance.vue')},
|
||||||
{path: 'transactions', name: routeNames.listLedgerTransactions, component: () => import('@/pages/ledger/ListLedgerTransactions.vue')},
|
{path: 'transactions', name: routeNames.listLedgerTransactions, component: () => import('@/pages/ledger/ListLedgerTransactions.vue')},
|
||||||
|
{path: 'acquisitions', name: routeNames.listLedgerAcquisitions, component: () => import('@/pages/ledger/ViewLedgerAcquisitions.vue')},
|
||||||
]},
|
]},
|
||||||
]},
|
]},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user