This commit is contained in:
seb
2026-10-10 18:17:14 +02:00
parent 004e0de869
commit a20668cd61
31 changed files with 572 additions and 76 deletions

View File

@@ -2,27 +2,37 @@ import { http } from './http.js';
export const attributename = {
/** GET /api/attributename → { attributenames: Attributename[] } */
// #region GET /api/attributename — list
list() {
return http('/api/attributename');
},
// #endregion
/** POST /api/attributename → 201 { attributename } */
// #region POST /api/attributename — create
create(body) {
return http('/api/attributename', { method: 'POST', body });
},
// #endregion
/** PATCH /api/attributename/:id → 200 { attributename } */
// #region PATCH /api/attributename/:id — update
update(id, body) {
return http(`/api/attributename/${encodeURIComponent(id)}`, { method: 'PATCH', body });
},
// #endregion
/** DELETE /api/attributename/:id → 200 */
// #region DELETE /api/attributename/:id — delete
delete(id) {
return http(`/api/attributename/${encodeURIComponent(id)}`, { method: 'DELETE' });
},
// #endregion
/** PUT /api/attributename/order → 200 */
// #region PUT /api/attributename/order — order
order(attributenameIds) {
return http('/api/attributename/order', { method: 'PUT', body: { attributenameIds } });
},
// #endregion
};

View File

@@ -2,33 +2,43 @@ import { http } from './http.js';
export const attributevalue = {
/** GET /api/attributename/:attributeId/value → { values: AttributeValue[] } */
// #region GET /api/attributename/:attributeId/value — listByAttributeId
listByAttributeId(attributeId) {
return http(`/api/attributename/${encodeURIComponent(attributeId)}/value`);
},
// #endregion
/** POST /api/attributename/:attributeId/value → 201 { attributevalue } */
// #region POST /api/attributename/:attributeId/value — create
create(attributeId, body) {
return http(`/api/attributename/${encodeURIComponent(attributeId)}/value`, {
method: 'POST',
body,
});
},
// #endregion
/** PATCH /api/attributevalue/:id → 200 { attributevalue } */
// #region PATCH /api/attributevalue/:id — update
update(id, body) {
return http(`/api/attributevalue/${encodeURIComponent(id)}`, { method: 'PATCH', body });
},
// #endregion
/** DELETE /api/attributevalue/:id → 200 */
// #region DELETE /api/attributevalue/:id — delete
delete(id) {
return http(`/api/attributevalue/${encodeURIComponent(id)}`, { method: 'DELETE' });
},
// #endregion
/** PUT /api/attributename/:attributeId/value/order → 200 */
// #region PUT /api/attributename/:attributeId/value/order — order
order(attributeId, attributevalueIds) {
return http(`/api/attributename/${encodeURIComponent(attributeId)}/value/order`, {
method: 'PUT',
body: { attributevalueIds },
});
},
// #endregion
};

View File

@@ -1,6 +1,7 @@
import { http, logApi } from './http.js';
export const auth = {
// #region GET /api/auth/me — me
async me() {
try {
const data = await http('/api/auth/me');
@@ -20,7 +21,9 @@ export const auth = {
throw err;
}
},
// #endregion
// #region POST /api/auth/login — loginWithGoogle
async loginWithGoogle(idToken) {
logApi('loginWithGoogle', {
idTokenLength: idToken?.length ?? 0,
@@ -41,7 +44,9 @@ export const auth = {
});
return { user: data.user, session };
},
// #endregion
// #region POST /api/auth/logout — logout
async logout() {
try {
await http('/api/auth/logout', { method: 'POST' });
@@ -49,4 +54,5 @@ export const auth = {
if (err.status !== 401) throw err;
}
},
// #endregion
};

View File

@@ -9,6 +9,7 @@ export const brand = {
* GET /api/brand → { brands: Brand[], total, offset, limit }
* @param {{ offset?: number, limit?: number, includeSmallThumbs?: boolean }} [params]
*/
// #region GET /api/brand — list
list(params) {
const offset = Number(params?.offset ?? 0);
const limit = Number(params?.limit ?? 0);
@@ -20,6 +21,7 @@ export const brand = {
const qs = query.toString();
return http(qs ? `/api/brand?${qs}` : '/api/brand');
},
// #endregion
/**
* POST /api/brand
@@ -27,32 +29,39 @@ export const brand = {
* Empty name ⇒ 400 Invalid brand.
* → 201 { brand: Brand } · 409 Brand already exists
*/
// #region POST /api/brand — create
create(body) {
return http('/api/brand', { method: 'POST', body });
},
// #endregion
/**
* PATCH /api/brand/:id
* Body: { name, gsprpinfo? } — rename / update info.
* → 200 { id, name, gsprpinfo, touchedArticleCount } · 404 Brand not found
*/
// #region PATCH /api/brand/:id — rename
rename(id, body) {
return http(`/api/brand/${encodeURIComponent(id)}`, { method: 'PATCH', body });
},
// #endregion
/**
* DELETE /api/brand/:id
* → 204 No Content · 404 Brand not found
*/
// #region DELETE /api/brand/:id — delete
delete(id) {
return http(`/api/brand/${encodeURIComponent(id)}`, { method: 'DELETE' });
},
// #endregion
/**
* POST /api/brand/:id/image
* Accepts full-size image body (Content-Type: image/webp).
* → 201 { brand: { id, fullHash, thumbW, thumbH, thumbHash, pics } }
*/
// #region POST /api/brand/:id/image — addImage
addImage(brandId, file) {
return httpBinary(`/api/brand/${brandId}/image`, {
method: 'POST',
@@ -60,12 +69,15 @@ export const brand = {
body: file,
});
},
// #endregion
/**
* DELETE /api/brand/:id/image
* → 200 { brand: { id, thumbW: null, thumbH: null, thumbHash: null, pics: [] } }
*/
// #region DELETE /api/brand/:id/image — deleteImage
deleteImage(brandId) {
return http(`/api/brand/${brandId}/image`, { method: 'DELETE' });
},
// #endregion
};

View File

@@ -2,34 +2,42 @@ import { http, httpBinary, httpGetBinary } from './http.js';
export const category = {
/** GET /api/category/tree → { languageId, tree, articles } (company from session) */
// #region GET /api/category/tree — getTree
getTree() {
return http('/api/category/tree');
},
// #endregion
/**
* GET /api/category/:id/articles → { articles: [...] }
* Article rows: sku, name, net, taxRate, fullHash, thumbW, thumbH, thumbHash, childCount, …
*/
// #region GET /api/category/:id/articles — getArticles
getArticles(categoryId) {
return http(`/api/category/${categoryId}/articles`);
},
// #endregion
/** POST /api/category → 201 { category } */
// #region POST /api/category — create
create({ parentId, name }) {
return http('/api/category', {
method: 'POST',
body: { parentId: Number(parentId), name },
});
},
// #endregion
/**
* DELETE /api/category/:id → 204
* Query: ?recursive=true (cascades deletion of subcategories and articles)
*/
// #region DELETE /api/category/:id — delete
delete(categoryId, { recursive = false } = {}) {
const qs = recursive ? '?recursive=true' : '';
return http(`/api/category/${categoryId}${qs}`, { method: 'DELETE' });
},
// #endregion
/**
* PATCH /api/category/:id
@@ -37,12 +45,14 @@ export const category = {
* Empty name → 400 name is required.
* → 200 { category: { id, name, slug } }
*/
// #region PATCH /api/category/:id — updateName
updateName(categoryId, name) {
return http(`/api/category/${categoryId}`, {
method: 'PATCH',
body: { name },
});
},
// #endregion
/**
* PUT /api/category/order
@@ -51,24 +61,28 @@ export const category = {
* set of parentId (same count, no foreign/duplicate ids) → 400 Invalid category order.
* → 200 { categoryIds: number[] }
*/
// #region PUT /api/category/order — reorder
reorder(parentId, categoryIds) {
return http('/api/category/order', {
method: 'PUT',
body: { parentId, categoryIds },
});
},
// #endregion
/**
* PATCH /api/category/:id
* Body: { parentId } — moves the category under a new parent.
* → 200 { category: { id, parentId, sort } } (kein name/slug im Response)
*/
// #region PATCH /api/category/:id — move
move(categoryId, parentId) {
return http(`/api/category/${categoryId}`, {
method: 'PATCH',
body: { parentId },
});
},
// #endregion
/**
* PATCH /api/category/:id
@@ -77,18 +91,21 @@ export const category = {
*
* PROPOSED — backend needs to implement this field.
*/
// #region PATCH /api/category/:id — updatePos
updatePos(categoryId, pos) {
return http(`/api/category/${categoryId}`, {
method: 'PATCH',
body: { pos },
});
},
// #endregion
/**
* POST /api/category/:id/image
* Body: raw image bytes (Content-Type: image/webp)
* → 201 { category: { id, fullHash, thumbW, thumbH, thumbHash } }
*/
// #region POST /api/category/:id/image — uploadImage
uploadImage(categoryId, file) {
return httpBinary(`/api/category/${categoryId}/image`, {
method: 'POST',
@@ -96,14 +113,17 @@ export const category = {
body: file,
});
},
// #endregion
/**
* DELETE /api/category/:id/image
* → 200 { category: { id, thumbW: null, thumbH: null, thumbHash: null } }
*/
// #region DELETE /api/category/:id/image — deleteImage
deleteImage(categoryId) {
return http(`/api/category/${categoryId}/image`, { method: 'DELETE' });
},
// #endregion
/**
* GET /api/category/export.zip → application/zip (binary download)
@@ -112,7 +132,9 @@ export const category = {
* entry per category image (content-addressed, deduplicated).
* Errors: 400 No company selected, 401, 403, 404 (JSON { error }).
*/
// #region GET /api/category/export.zip — exportZip
exportZip() {
return httpGetBinary('/api/category/export.zip');
},
// #endregion
};

View File

@@ -2,42 +2,52 @@ import { http } from './http.js';
export const company = {
/** GET /api/company → { companies: [...] } */
// #region GET /api/company — list
list() {
return http('/api/company');
},
// #endregion
/** Uses GET /api/company until a dedicated endpoint exists. */
// #region GET /api/company — getById
async getById(companyId) {
const data = await http('/api/company');
const found = data.companies?.find((item) => item.id === companyId);
if (!found) throw new Error('Unternehmen nicht gefunden.');
return { company: found };
},
// #endregion
// #region POST /api/company — create
create({ name, iso639, taxrate, reducedtaxrate }) {
return http('/api/company', {
method: 'POST',
body: { name, iso639, taxrate, reducedtaxrate },
});
},
// #endregion
/**
* PUT /api/company/:companyId
* Body: { name, iso639, taxrate, reducedtaxrate }
*/
// #region PUT /api/company/:companyId — update
update(companyId, { name, iso639, taxrate, reducedtaxrate }) {
return http(`/api/company/${companyId}`, {
method: 'PUT',
body: { name, iso639, taxrate, reducedtaxrate },
});
},
// #endregion
// #region PUT /api/auth/selected-company — select
select(companyId) {
return http('/api/auth/selected-company', {
method: 'PUT',
body: { companyId },
});
},
// #endregion
/**
* POST /api/company/import
@@ -48,12 +58,14 @@ export const company = {
* @param {object} [callbacks]
* @param {(progress: { loaded: number, total: number, percent: number }) => void} [callbacks.onUploadProgress]
* @param {(message: string) => void} [callbacks.onStatus]
* @param {(progress: { phase: string, current: number, total: number, item?: string }) => void} [callbacks.onProgress]
* @param {(progress: { categoriestotal: number, categoriesdone: number, articlestotal: number, articlesdone: number, imagestotal: number, imagesdone: number, receiptstotal: number, receiptsdone: number }) => void} [callbacks.onProgress] Counter-based progress snapshot across all phases.
* @param {(images: string[]) => void} [callbacks.onImages] Batched `images` events (~every 100ms) carrying Base62 SkeleHash strings.
* @param {(stats: object) => void} [callbacks.onDone]
* @param {(error: string) => void} [callbacks.onError]
* @param {object} [options]
* @param {AbortSignal} [options.signal]
*/
// #region POST /api/company/import — importCatalog
importCatalog(file, callbacks = {}, { signal } = {}) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
@@ -122,6 +134,21 @@ export const company = {
case 'progress':
callbacks.onProgress?.(eventData);
break;
case 'images': {
// Payload is a plain array of Base62 SkeleHash strings;
// also tolerate the { images: [...] } wrapper shape.
const list = Array.isArray(eventData)
? eventData
: Array.isArray(eventData?.images)
? eventData.images
: [];
if (list.length) callbacks.onImages?.(list);
break;
}
case 'image':
// Legacy: single image event (pre-batching).
if (eventData) callbacks.onImages?.([eventData]);
break;
case 'done':
callbacks.onDone?.(eventData?.stats ?? eventData);
break;
@@ -165,4 +192,5 @@ export const company = {
xhr.send(formData);
});
},
// #endregion
};

View File

@@ -8,9 +8,11 @@ import { http } from './http.js';
*/
export const customergroup = {
/** GET /api/customergroup → { customergroups: (CustomerGroup & { editable })[] } ordered by sort */
// #region GET /api/customergroup — list
list() {
return http('/api/customergroup');
},
// #endregion
/**
* POST /api/customergroup
@@ -18,18 +20,22 @@ export const customergroup = {
* reserved POS / Lieferanten ⇒ 400 Name not allowed; sort appends next index.
* → 201 { customergroup: CustomerGroup }
*/
// #region POST /api/customergroup — create
create(body) {
return http('/api/customergroup', { method: 'POST', body });
},
// #endregion
/**
* PATCH /api/customergroup/:id
* Body: { name } — locked groups cannot be renamed (Name cannot be changed).
* → 200 { customergroup: CustomerGroup }
*/
// #region PATCH /api/customergroup/:id — update
update(id, body) {
return http(`/api/customergroup/${id}`, { method: 'PATCH', body });
},
// #endregion
/**
* PUT /api/customergroup/order
@@ -37,12 +43,16 @@ export const customergroup = {
* else 400 Invalid customer group order. Sets sort to each id’s index 0…n-1.
* → 200 { customergroupIds: number[] }
*/
// #region PUT /api/customergroup/order — order
order(body) {
return http('/api/customergroup/order', { method: 'PUT', body });
},
// #endregion
/** DELETE /api/customergroup/:id → 204 · 409 Customer group in use */
// #region DELETE /api/customergroup/:id — delete
delete(id) {
return http(`/api/customergroup/${id}`, { method: 'DELETE' });
},
// #endregion
};

View File

@@ -11,14 +11,18 @@ import { http, clientIdHeaders } from './http.js';
*/
export const delivery = {
/** GET /api/delivery → { deliveries: DeliverySummary[] } */
// #region GET /api/delivery — list
list() {
return http('/api/delivery');
},
// #endregion
/** GET /api/delivery/:id → { delivery: Delivery } */
// #region GET /api/delivery/:id — get
get(id) {
return http(`/api/delivery/${id}`);
},
// #endregion
/**
* POST /api/delivery
@@ -28,9 +32,11 @@ export const delivery = {
* Line requires sku, amount, net, tax. rebate→0, transactedAmount→amount.
* → 201 { delivery: Delivery }
*/
// #region POST /api/delivery — create
create(body) {
return http('/api/delivery', { method: 'POST', body });
},
// #endregion
/**
* PATCH /api/delivery/:id
@@ -40,19 +46,24 @@ export const delivery = {
* If lines present, replaces all lines; if omitted, lines unchanged.
* → 200 { delivery: Delivery }
*/
// #region PATCH /api/delivery/:id — update
update(id, body) {
return http(`/api/delivery/${id}`, { method: 'PATCH', body });
},
// #endregion
/** DELETE /api/delivery/:id → 204 */
// #region DELETE /api/delivery/:id — delete
delete(id) {
return http(`/api/delivery/${id}`, { method: 'DELETE' });
},
// #endregion
/**
* GET /api/delivery/:id/file/:fileId → Blob
* Full binary content of attached file (PDF, text, etc.)
*/
// #region GET /api/delivery/:id/file/:fileId — getFile
async getFile(id, fileId, { download = false } = {}) {
const query = download ? '?download=true' : '';
const res = await fetch(`/api/delivery/${encodeURIComponent(id)}/file/${encodeURIComponent(fileId)}${query}`, {
@@ -71,12 +82,14 @@ export const delivery = {
}
return res.blob();
},
// #endregion
/**
* POST /api/delivery/parse — multipart/form-data, field "file"
* Accepts PDF, TXT or CSV document (max 50 MB)
* Streams SSE events: status, llm_call, tool_call, usage, progress, result, error
*/
// #region POST /api/delivery/parse — parseSse
async *parseSse(file, { signal } = {}) {
const formData = new FormData();
formData.append('file', file, file.name);
@@ -148,4 +161,5 @@ export const delivery = {
} catch { /* ignore */ }
}
},
// #endregion
};

View File

@@ -9,6 +9,7 @@ export const entity = {
* GET /api/entity → { entities: Entity[] }
* Optional query: customergroupId
*/
// #region GET /api/entity — list
list({ customergroupId } = {}) {
const qs =
customergroupId != null
@@ -16,83 +17,110 @@ export const entity = {
: '';
return http(`/api/entity${qs}`);
},
// #endregion
/** GET /api/entity/:id → { entity: Entity } */
// #region GET /api/entity/:id — get
get(id) {
return http(`/api/entity/${id}`);
},
// #endregion
/**
* POST /api/entity
* Body: { customergroupId, name, firstName? }
* → 201 { entity: Entity }
*/
// #region POST /api/entity — create
create(body) {
return http('/api/entity', { method: 'POST', body });
},
// #endregion
/**
* PATCH /api/entity/:id
* Body: { name?, firstName? }
* → 200 { entity: Entity }
*/
// #region PATCH /api/entity/:id — update
update(id, body) {
return http(`/api/entity/${id}`, { method: 'PATCH', body });
},
// #endregion
/** DELETE /api/entity/:id → 204 */
// #region DELETE /api/entity/:id — delete
delete(id) {
return http(`/api/entity/${id}`, { method: 'DELETE' });
},
// #endregion
/** GET /api/entity/next-number → { number: string } */
// #region GET /api/entity/next-number — nextNumber
nextNumber() {
return http('/api/entity/next-number');
},
// #endregion
/** GET /api/entity/:entityId/address → { addresses: EntityAddress[] } */
// #region GET /api/entity/:entityId/address — listAddresses
listAddresses(entityId) {
return http(`/api/entity/${entityId}/address`);
},
// #endregion
/** POST /api/entity/:entityId/address → 201 { address } */
// #region POST /api/entity/:entityId/address — createAddress
createAddress(entityId, body) {
return http(`/api/entity/${entityId}/address`, { method: 'POST', body });
},
// #endregion
/** PATCH /api/entity/:entityId/address/:id → { address } */
// #region PATCH /api/entity/:entityId/address/:id — updateAddress
updateAddress(entityId, id, body) {
return http(`/api/entity/${entityId}/address/${id}`, {
method: 'PATCH',
body,
});
},
// #endregion
/** DELETE /api/entity/:entityId/address/:id → 204 */
// #region DELETE /api/entity/:entityId/address/:id — deleteAddress
deleteAddress(entityId, id) {
return http(`/api/entity/${entityId}/address/${id}`, { method: 'DELETE' });
},
// #endregion
/** GET /api/entity/:entityId/contact → { contacts: EntityContact[] } */
// #region GET /api/entity/:entityId/contact — listContacts
listContacts(entityId) {
return http(`/api/entity/${entityId}/contact`);
},
// #endregion
/** POST /api/entity/:entityId/contact → 201 { contact } */
// #region POST /api/entity/:entityId/contact — createContact
createContact(entityId, body) {
return http(`/api/entity/${entityId}/contact`, { method: 'POST', body });
},
// #endregion
/** PATCH /api/entity/:entityId/contact/:id → { contact } */
// #region PATCH /api/entity/:entityId/contact/:id — updateContact
updateContact(entityId, id, body) {
return http(`/api/entity/${entityId}/contact/${id}`, {
method: 'PATCH',
body,
});
},
// #endregion
/** DELETE /api/entity/:entityId/contact/:id → 204 */
// #region DELETE /api/entity/:entityId/contact/:id — deleteContact
deleteContact(entityId, id) {
return http(`/api/entity/${entityId}/contact/${id}`, { method: 'DELETE' });
},
// #endregion
};

View File

@@ -5,6 +5,7 @@ export const globalHistory = {
* GET /api/history
* Global system/entity history with paging/sorting/filtering
*/
// #region GET /api/history — list
list({ startRow, endRow, offset, limit, sortModel, filterModel } = {}) {
const params = new URLSearchParams();
if (startRow != null) params.set('startRow', String(startRow));
@@ -16,4 +17,5 @@ export const globalHistory = {
const qs = params.toString();
return http(`/api/history${qs ? `?${qs}` : ''}`);
},
// #endregion
};

View File

@@ -6,37 +6,47 @@ import { http } from './http.js';
*/
export const labeltemplate = {
/** GET /api/labeltemplate → { labeltemplates: LabelTemplate[] } */
// #region GET /api/labeltemplate — list
list() {
return http('/api/labeltemplate');
},
// #endregion
/** GET /api/labeltemplate/:id → { labeltemplate: LabelTemplate } */
// #region GET /api/labeltemplate/:id — get
get(id) {
return http(`/api/labeltemplate/${encodeURIComponent(id)}`);
},
// #endregion
/**
* POST /api/labeltemplate
* Body: { name, width, height, dpi, type, content }
* → 201 { labeltemplate: LabelTemplate }
*/
// #region POST /api/labeltemplate — create
create(body) {
return http('/api/labeltemplate', { method: 'POST', body });
},
// #endregion
/**
* PATCH /api/labeltemplate/:id
* Body: partial { name?, width?, height?, dpi?, type?, content? }
* → 200 { labeltemplate: LabelTemplate }
*/
// #region PATCH /api/labeltemplate/:id — update
update(id, body) {
return http(`/api/labeltemplate/${encodeURIComponent(id)}`, { method: 'PATCH', body });
},
// #endregion
/** DELETE /api/labeltemplate/:id → 204 */
// #region DELETE /api/labeltemplate/:id — delete
delete(id) {
return http(`/api/labeltemplate/${encodeURIComponent(id)}`, { method: 'DELETE' });
},
// #endregion
// thumb is returned inline as a base64 string in list/get responses
};

View File

@@ -11,35 +11,42 @@ export const ledger = {
* Body: { manifestarticle_id, transaction_type, amount, transaction_text }
* → 201 { ledger: LedgerEntry }
*/
// #region POST /api/ledger — add
add(body) {
return http('/api/ledger', { method: 'POST', body });
},
// #endregion
/**
* GET /api/ledger/manifestarticle/:manifestarticleId
* Query: ?transaction_type=...
* → 200 { ledger: LedgerEntry[] }
*/
// #region GET /api/ledger/manifestarticle/:manifestarticleId — listByManifestarticleId
listByManifestarticleId(manifestarticleId, transactionType) {
const query = transactionType ? `?transaction_type=${encodeURIComponent(transactionType)}` : '';
return http(`/api/ledger/manifestarticle/${encodeURIComponent(manifestarticleId)}${query}`);
},
// #endregion
/**
* GET /api/ledger/sku/:sku
* Query: ?transaction_type=...
* → 200 { ledger: LedgerEntry[] }
*/
// #region GET /api/ledger/sku/:sku — listBySku
listBySku(sku, transactionType) {
const query = transactionType ? `?transaction_type=${encodeURIComponent(transactionType)}` : '';
return http(`/api/ledger/sku/${encodeURIComponent(sku)}${query}`);
},
// #endregion
/**
* GET /api/ledger
* Query: { manifestarticle_id?, sku?, transaction_type? }
* → 200 { ledger: LedgerEntry[] }
*/
// #region GET /api/ledger — list
list(query) {
const params = new URLSearchParams();
if (query?.manifestarticle_id != null) params.set('manifestarticle_id', query.manifestarticle_id);
@@ -50,4 +57,5 @@ export const ledger = {
const qs = params.toString();
return http(`/api/ledger${qs ? `?${qs}` : ''}`);
},
// #endregion
};

View File

@@ -6,18 +6,22 @@ export const modelconversation = {
* Lists the user's model conversations in the selected company.
* → 200 { conversations: [{ id, companyuser_id, provider, model, created_at, updated_at, state }] }
*/
// #region GET /api/modelconversation — list
list() {
return http('/api/modelconversation');
},
// #endregion
/**
* GET /api/modelconversation/:id
* Fetch conversation details by ID.
* @param {number|string} id
*/
// #region GET /api/modelconversation/:id — get
get(id) {
return http(`/api/modelconversation/${encodeURIComponent(id)}`);
},
// #endregion
/**
* POST /api/modelconversation
@@ -25,27 +29,35 @@ export const modelconversation = {
* Body: { provider, model }
* → 201 { conversation: { id, companyuser_id, provider, model, created_at, updated_at, state } }
*/
// #region POST /api/modelconversation — create
create(body) {
return http('/api/modelconversation', { method: 'POST', body });
},
// #endregion
/**
* GET /api/modelconversation/:id/message
* Lists conversation messages, oldest first.
* → 200 { messages: [{ id, conversation_id, created_at, role, message }] }
*/
// #region GET /api/modelconversation/:id/message — listMessages
listMessages(id) {
return http(`/api/modelconversation/${encodeURIComponent(id)}/message`);
},
// #endregion
// #region POST /api/modelconversation/:id/message — addMessage
addMessage(id, body) {
return http(`/api/modelconversation/${encodeURIComponent(id)}/message`, { method: 'POST', body });
},
// #endregion
/**
* DELETE /api/modelconversation/:id
*/
// #region DELETE /api/modelconversation/:id — delete
delete(id) {
return http(`/api/modelconversation/${encodeURIComponent(id)}`, { method: 'DELETE' });
},
// #endregion
};

View File

@@ -5,16 +5,20 @@ export const number = {
* GET /api/number → { numbers: [{ id, type, prefix, padding, next }] }
* Lists the number sequences for the selected company.
*/
// #region GET /api/number — list
list() {
return http('/api/number');
},
// #endregion
/**
* PATCH /api/number/:id
* Body: at least one of { prefix, padding, next } — only present keys are patched.
* → 200 { number: { id, type, prefix, padding, next } }
*/
// #region PATCH /api/number/:id — update
update(id, body) {
return http(`/api/number/${id}`, { method: 'PATCH', body });
},
// #endregion
};

View File

@@ -11,6 +11,7 @@ export const order = {
* @param {{ offset?: number, limit?: number }} [params]
* → { orders: Order[], total: number, offset: number, limit: number }
*/
// #region GET /api/order — list
list({ offset = 0, limit = 20 } = {}) {
const params = new URLSearchParams();
if (offset != null) params.set('offset', String(offset));
@@ -18,32 +19,41 @@ export const order = {
const qs = params.toString();
return http(`/api/order${qs ? `?${qs}` : ''}`);
},
// #endregion
/** GET /api/order/:id → { order: Order } */
// #region GET /api/order/:id — get
get(id) {
return http(`/api/order/${id}`);
},
// #endregion
/**
* POST /api/order
* Body: { number, date, entityId?, lines }
* → 201 { order: Order }
*/
// #region POST /api/order — create
create(body) {
return http('/api/order', { method: 'POST', body });
},
// #endregion
/**
* PATCH /api/order/:id
* Body: partial { number?, date?, entityId?, lines? }
* → 200 { order: Order }
*/
// #region PATCH /api/order/:id — update
update(id, body) {
return http(`/api/order/${id}`, { method: 'PATCH', body });
},
// #endregion
/** DELETE /api/order/:id → 204 */
// #region DELETE /api/order/:id — delete
delete(id) {
return http(`/api/order/${id}`, { method: 'DELETE' });
},
// #endregion
};

View File

@@ -5,9 +5,11 @@ export const posterminal = {
* GET /api/posterminal → { posterminals: [{ id, name, token, pairingpin }] }
* List all terminals for the selected company.
*/
// #region GET /api/posterminal — list
list() {
return http('/api/posterminal');
},
// #endregion
/**
* PUT /api/posterminal
@@ -15,12 +17,14 @@ export const posterminal = {
* Creates a new terminal (auto-generates 6-digit pin).
* → 200 { posterminal: { id, name, token, pairingpin } }
*/
// #region PUT /api/posterminal — create
create({ name }) {
return http('/api/posterminal', {
method: 'PUT',
body: { name },
});
},
// #endregion
/**
* PATCH /api/posterminal/:id
@@ -28,64 +32,76 @@ export const posterminal = {
* Update posterminal configuration.
* → 200 { posterminal }
*/
// #region PATCH /api/posterminal/:id — update
update(terminalId, patch) {
return http(`/api/posterminal/${terminalId}`, {
method: 'PATCH',
body: patch,
});
},
// #endregion
/**
* DELETE /api/posterminal/:id → 204
* Deletes a terminal.
*/
// #region DELETE /api/posterminal/:id — delete
delete(terminalId) {
return http(`/api/posterminal/${terminalId}`, {
method: 'DELETE',
});
},
// #endregion
/**
* PUT /api/posterminal/:id/category/:categoryId
* Enable a category on a terminal.
* → 200 { id: number, categoryIds: number[] }
*/
// #region PUT /api/posterminal/:id/category/:categoryId — enableCategory
enableCategory(terminalId, categoryId) {
return http(`/api/posterminal/${terminalId}/category/${categoryId}`, {
method: 'PUT',
});
},
// #endregion
/**
* DELETE /api/posterminal/:id/category/:categoryId
* Disable a category on a terminal.
* → 200 { id: number, categoryIds: number[] }
*/
// #region DELETE /api/posterminal/:id/category/:categoryId — disableCategory
disableCategory(terminalId, categoryId) {
return http(`/api/posterminal/${terminalId}/category/${categoryId}`, {
method: 'DELETE',
});
},
// #endregion
/**
* PUT /api/posterminal/:id/all
* Enable all categories on a terminal.
* → 200 { id: number, categoryIds: number[] }
*/
// #region PUT /api/posterminal/:id/all — enableAllCategories
enableAllCategories(terminalId) {
return http(`/api/posterminal/${terminalId}/all`, {
method: 'PUT',
});
},
// #endregion
/**
* DELETE /api/posterminal/:id/all
* Disable all categories on a terminal.
* → 200 { id: number, categoryIds: number[] }
*/
// #region DELETE /api/posterminal/:id/all — disableAllCategories
disableAllCategories(terminalId) {
return http(`/api/posterminal/${terminalId}/all`, {
method: 'DELETE',
});
},
// #endregion
};

View File

@@ -6,44 +6,56 @@ import { http } from './http.js';
*/
export const printer = {
/** GET /api/printer → { printers: Printer[] } */
// #region GET /api/printer — list
list() {
return http('/api/printer');
},
// #endregion
/** GET /api/printer/:id → { printer: Printer } */
// #region GET /api/printer/:id — getById
getById(id) {
return http(`/api/printer/${id}`);
},
// #endregion
/**
* POST /api/printer
* Body: { address, type, model, serial, sort, desc }
* → 201 { printer: Printer }
*/
// #region POST /api/printer — create
create(body) {
return http('/api/printer', { method: 'POST', body });
},
// #endregion
/**
* PATCH /api/printer/:id
* Body: partial printer fields
* → 200 { printer: Printer }
*/
// #region PATCH /api/printer/:id — update
update(id, body) {
return http(`/api/printer/${id}`, { method: 'PATCH', body });
},
// #endregion
/** DELETE /api/printer/:id → 204 */
// #region DELETE /api/printer/:id — delete
delete(id) {
return http(`/api/printer/${id}`, { method: 'DELETE' });
},
// #endregion
/**
* PUT /api/printer/order
* Body: { printerIds: number[] }
* → 200 { printerIds: number[] }
*/
// #region PUT /api/printer/order — order
order({ printerIds }) {
return http('/api/printer/order', { method: 'PUT', body: { printerIds } });
},
// #endregion
};

View File

@@ -2,27 +2,37 @@ import { http } from './http.js';
export const propertyname = {
/** GET /api/propertyname → { propertynames: Propertyname[] } */
// #region GET /api/propertyname — list
list() {
return http('/api/propertyname');
},
// #endregion
/** POST /api/propertyname → 201 { propertyname } */
// #region POST /api/propertyname — create
create(body) {
return http('/api/propertyname', { method: 'POST', body });
},
// #endregion
/** PATCH /api/propertyname/:id → 200 { propertyname } */
// #region PATCH /api/propertyname/:id — update
update(id, body) {
return http(`/api/propertyname/${encodeURIComponent(id)}`, { method: 'PATCH', body });
},
// #endregion
/** DELETE /api/propertyname/:id → 200 */
// #region DELETE /api/propertyname/:id — delete
delete(id) {
return http(`/api/propertyname/${encodeURIComponent(id)}`, { method: 'DELETE' });
},
// #endregion
/** PUT /api/propertyname/order → 200 */
// #region PUT /api/propertyname/order — order
order(propertynameIds) {
return http('/api/propertyname/order', { method: 'PUT', body: { propertynameIds } });
},
// #endregion
};

View File

@@ -8,35 +8,45 @@ import { http } from './http.js';
*/
export const quote = {
/** GET /api/quote → { quotes: QuoteSummary[] } */
// #region GET /api/quote — list
list() {
return http('/api/quote');
},
// #endregion
/** GET /api/quote/:id → { quote: Quote } */
// #region GET /api/quote/:id — get
get(id) {
return http(`/api/quote/${id}`);
},
// #endregion
/**
* POST /api/quote
* Body: { number, date, entityId?, lines }
* → 201 { quote: Quote }
*/
// #region POST /api/quote — create
create(body) {
return http('/api/quote', { method: 'POST', body });
},
// #endregion
/**
* PATCH /api/quote/:id
* Body: partial { number?, date?, entityId?, lines? }
* → 200 { quote: Quote }
*/
// #region PATCH /api/quote/:id — update
update(id, body) {
return http(`/api/quote/${id}`, { method: 'PATCH', body });
},
// #endregion
/** DELETE /api/quote/:id → 204 */
// #region DELETE /api/quote/:id — delete
delete(id) {
return http(`/api/quote/${id}`, { method: 'DELETE' });
},
// #endregion
};

View File

@@ -9,24 +9,30 @@ export const setting = {
* GET /api/company/setting
* Optional query: { frontendOnly } → 200 { settings: Setting[] }
*/
// #region GET /api/company/setting — list
list({ frontendOnly } = {}) {
const qs = frontendOnly ? '?frontendOnly=1' : '';
return http(`/api/company/setting${qs}`);
},
// #endregion
/** GET /api/company/setting/:key → { setting: Setting } */
// #region GET /api/company/setting/:key — get
get(key) {
return http(`/api/company/setting/${encodeURIComponent(key)}`);
},
// #endregion
/**
* PUT /api/company/setting/:key
* Body: { value, frontend } → 200 { setting: Setting }
*/
// #region PUT /api/company/setting/:key — upsert
upsert(key, body) {
return http(`/api/company/setting/${encodeURIComponent(key)}`, {
method: 'PUT',
body,
});
},
// #endregion
};

View File

@@ -8,7 +8,9 @@ export const stock = {
* POST /api/stock/adjust
* Body: { sku, warehouseId, amount, text?, date?, externalNumber?, lines? }
*/
// #region POST /api/stock/adjust — adjust
adjust(body) {
return http('/api/stock/adjust', { method: 'POST', body });
},
// #endregion
};

View File

@@ -6,37 +6,46 @@ import { http } from './http.js';
*/
export const supplier = {
/** GET /api/supplier → { suppliers: Supplier[] } */
// #region GET /api/supplier — list
list() {
return http('/api/supplier');
},
// #endregion
/**
* POST /api/supplier
* Body: { name } — empty name ⇒ 400 Name required.
* → 201 { supplier: Supplier }
*/
// #region POST /api/supplier — create
create(body) {
return http('/api/supplier', { method: 'POST', body });
},
// #endregion
/**
* PATCH /api/supplier/:id
* Body: { name } — empty name ⇒ 400 Name required.
* → 200 { supplier: Supplier }
*/
// #region PATCH /api/supplier/:id — update
update(id, body) {
return http(`/api/supplier/${id}`, { method: 'PATCH', body });
},
// #endregion
/** DELETE /api/supplier/:id → 204 */
// #region DELETE /api/supplier/:id — delete
delete(id) {
return http(`/api/supplier/${id}`, { method: 'DELETE' });
},
// #endregion
/**
* GET /api/supplier/:id/articles?skus=...
* → 200 { articles: SupplierArticle[] }
*/
// #region GET /api/supplier/:id/articles — getArticles
getArticles(id, skus) {
let query = '';
if (skus != null) {
@@ -48,4 +57,5 @@ export const supplier = {
}
return http(`/api/supplier/${encodeURIComponent(id)}/articles${query}`);
},
// #endregion
};

View File

@@ -7,7 +7,9 @@ export const thumb = {
* GET /api/thumb/:fullHash → image/avif (thumb bytes)
* Use as <img src={thumb.url(fullHash)} /> (same-origin; cookies sent).
*/
// #region GET /api/thumb/:fullHash — url
url(fullHash) {
return `/api/thumb/${encodeURIComponent(fullHash)}`;
},
// #endregion
};

View File

@@ -6,25 +6,31 @@ import { http } from './http.js';
*/
export const unit = {
/** GET /api/unit → { units: [...] } · 400 No company selected */
// #region GET /api/unit — list
list() {
return http('/api/unit');
},
// #endregion
/**
* PUT /api/unit
* Body: { si, basesi, basesifactor, symbol, name }
* → 200 { unit }
*/
// #region PUT /api/unit — upsert
upsert(body) {
return http('/api/unit', { method: 'PUT', body });
},
// #endregion
/**
* DELETE /api/unit?si=… → 204
* 409 Unit in use
*/
// #region DELETE /api/unit?si=… — delete
delete(si) {
const params = new URLSearchParams({ si });
return http(`/api/unit?${params}`, { method: 'DELETE' });
},
// #endregion
};

View File

@@ -6,15 +6,18 @@ export const vfs = {
* List files in the virtual filesystem for the selected company.
* → 200 { files: [{ name, size, mime, updated_at, created_at, isText, isImage, isPdf }] }
*/
// #region GET /api/vfs — list
list() {
return http('/api/vfs');
},
// #endregion
/**
* GET /api/vfs/*path
* Fetch raw content of a file (e.g. text for the editor).
* @param {string} path
*/
// #region GET /api/vfs/*path — getText
async getText(path) {
const clean = String(path || '').replace(/^\/+/, '');
const res = await fetch(`/api/vfs/${clean}?raw=1`, {
@@ -25,6 +28,7 @@ export const vfs = {
}
return res.text();
},
// #endregion
/**
* PUT /api/vfs/*path
@@ -33,6 +37,7 @@ export const vfs = {
* @param {string} content
* @param {string} [mime]
*/
// #region PUT /api/vfs/*path — save
save(path, content, mime) {
const clean = String(path || '').replace(/^\/+/, '');
return http(`/api/vfs/${clean}`, {
@@ -40,18 +45,21 @@ export const vfs = {
body: { content, mime },
});
},
// #endregion
/**
* DELETE /api/vfs/*path
* Delete a file.
* @param {string} path
*/
// #region DELETE /api/vfs/*path — delete
delete(path) {
const clean = String(path || '').replace(/^\/+/, '');
return http(`/api/vfs/${clean}`, {
method: 'DELETE',
});
},
// #endregion
/**
* POST /api/vfs/upload
@@ -59,6 +67,7 @@ export const vfs = {
* @param {File[]|FileList|File} files
* @param {string} [targetDir]
*/
// #region POST /api/vfs/upload — upload
async upload(files, targetDir = '') {
const formData = new FormData();
if (targetDir) formData.append('targetDir', targetDir);
@@ -78,12 +87,14 @@ export const vfs = {
}
return res.json();
},
// #endregion
/**
* POST /api/vfs/mkdir
* Create a directory in VFS.
* @param {string} path
*/
// #region POST /api/vfs/mkdir — mkdir
mkdir(path) {
const clean = String(path || '').replace(/^\/+/, '');
return http('/api/vfs/mkdir', {
@@ -91,6 +102,7 @@ export const vfs = {
body: { path: clean },
});
},
// #endregion
/**
* POST /api/vfs/rename
@@ -98,6 +110,7 @@ export const vfs = {
* @param {string} oldPath
* @param {string} newPath
*/
// #region POST /api/vfs/rename — rename
rename(oldPath, newPath) {
const cleanOld = String(oldPath || '').replace(/^\/+/, '');
const cleanNew = String(newPath || '').replace(/^\/+/, '');
@@ -106,6 +119,7 @@ export const vfs = {
body: { oldPath: cleanOld, newPath: cleanNew },
});
},
// #endregion
/**
* POST /api/vfs/*path — run a `.applet.js` file from VFS.
@@ -116,6 +130,7 @@ export const vfs = {
* `result` is a typed CSV string (`;`-separated, header row first), `columns` are the
* declared `{ name, type }` pairs, `rows` is the data-row count.
*/
// #region POST /api/vfs/*path — runApplet
runApplet(path, options = {}) {
const clean = String(path || '').replace(/^\/+/, '');
const body = {};
@@ -127,4 +142,5 @@ export const vfs = {
body,
});
},
// #endregion
};

View File

@@ -6,44 +6,56 @@ import { http } from './http.js';
*/
export const warehouse = {
/** GET /api/warehouse → { warehouses: Warehouse[] } */
// #region GET /api/warehouse — list
list() {
return http('/api/warehouse');
},
// #endregion
/** GET /api/warehouse/:id → { warehouse: Warehouse } */
// #region GET /api/warehouse/:id — getById
getById(id) {
return http(`/api/warehouse/${id}`);
},
// #endregion
/**
* POST /api/warehouse
* Body: { name, sort? } — empty name ⇒ 400 Name required.
* → 201 { warehouse: Warehouse }
*/
// #region POST /api/warehouse — create
create(body) {
return http('/api/warehouse', { method: 'POST', body });
},
// #endregion
/**
* PATCH /api/warehouse/:id
* Body: { name?, sort? }
* → 200 { warehouse: Warehouse }
*/
// #region PATCH /api/warehouse/:id — update
update(id, body) {
return http(`/api/warehouse/${id}`, { method: 'PATCH', body });
},
// #endregion
/**
* PUT /api/warehouse/order
* Body: { warehouseIds: number[] }
* → 200 { warehouseIds: number[] }
*/
// #region PUT /api/warehouse/order — order
order(body) {
return http('/api/warehouse/order', { method: 'PUT', body });
},
// #endregion
/** DELETE /api/warehouse/:id → 204 */
// #region DELETE /api/warehouse/:id — delete
delete(id) {
return http(`/api/warehouse/${id}`, { method: 'DELETE' });
},
// #endregion
};