Add Kunde CRUD with addresses/contacts, delivery edit, and Auftrag sub-nav.
Wire customergroup/entity APIs, Lieferungen detail editing, and Angebot/Bestellung/Ausliefern/Retoure placeholders.
This commit is contained in:
@@ -95,6 +95,59 @@ export class ApiClient {
|
||||
delete: (id) => this.#empty('DELETE', `/api/delivery/${enc(id)}`),
|
||||
};
|
||||
|
||||
this.customergroup = {
|
||||
/** GET /api/customergroup → { customergroups } */
|
||||
list: () => this.#json('GET', '/api/customergroup'),
|
||||
/** POST /api/customergroup → 201 { customergroup } */
|
||||
create: (body) => this.#json('POST', '/api/customergroup', { body }),
|
||||
/** PATCH /api/customergroup/{id} → { customergroup } */
|
||||
update: (id, body) =>
|
||||
this.#json('PATCH', `/api/customergroup/${enc(id)}`, { body }),
|
||||
/** DELETE /api/customergroup/{id} → 204 */
|
||||
delete: (id) => this.#empty('DELETE', `/api/customergroup/${enc(id)}`),
|
||||
};
|
||||
|
||||
this.entity = {
|
||||
/** GET /api/entity → { entities } · optional query customergroupId */
|
||||
list: (query) => this.#json('GET', '/api/entity', { query }),
|
||||
/** GET /api/entity/{id} → { entity } */
|
||||
get: (id) => this.#json('GET', `/api/entity/${enc(id)}`),
|
||||
/** POST /api/entity → 201 { entity } */
|
||||
create: (body) => this.#json('POST', '/api/entity', { body }),
|
||||
/** PATCH /api/entity/{id} → { entity } */
|
||||
update: (id, body) => this.#json('PATCH', `/api/entity/${enc(id)}`, { body }),
|
||||
/** DELETE /api/entity/{id} → 204 */
|
||||
delete: (id) => this.#empty('DELETE', `/api/entity/${enc(id)}`),
|
||||
/** GET /api/entity/{entityId}/address → { addresses } */
|
||||
listAddresses: (entityId) =>
|
||||
this.#json('GET', `/api/entity/${enc(entityId)}/address`),
|
||||
/** POST /api/entity/{entityId}/address → 201 { address } */
|
||||
createAddress: (entityId, body) =>
|
||||
this.#json('POST', `/api/entity/${enc(entityId)}/address`, { body }),
|
||||
/** PATCH /api/entity/{entityId}/address/{id} → { address } */
|
||||
updateAddress: (entityId, id, body) =>
|
||||
this.#json('PATCH', `/api/entity/${enc(entityId)}/address/${enc(id)}`, {
|
||||
body,
|
||||
}),
|
||||
/** DELETE /api/entity/{entityId}/address/{id} → 204 */
|
||||
deleteAddress: (entityId, id) =>
|
||||
this.#empty('DELETE', `/api/entity/${enc(entityId)}/address/${enc(id)}`),
|
||||
/** GET /api/entity/{entityId}/contact → { contacts } */
|
||||
listContacts: (entityId) =>
|
||||
this.#json('GET', `/api/entity/${enc(entityId)}/contact`),
|
||||
/** POST /api/entity/{entityId}/contact → 201 { contact } */
|
||||
createContact: (entityId, body) =>
|
||||
this.#json('POST', `/api/entity/${enc(entityId)}/contact`, { body }),
|
||||
/** PATCH /api/entity/{entityId}/contact/{id} → { contact } */
|
||||
updateContact: (entityId, id, body) =>
|
||||
this.#json('PATCH', `/api/entity/${enc(entityId)}/contact/${enc(id)}`, {
|
||||
body,
|
||||
}),
|
||||
/** DELETE /api/entity/{entityId}/contact/{id} → 204 */
|
||||
deleteContact: (entityId, id) =>
|
||||
this.#empty('DELETE', `/api/entity/${enc(entityId)}/contact/${enc(id)}`),
|
||||
};
|
||||
|
||||
this.category = {
|
||||
/** GET /api/category/tree */
|
||||
tree: () => this.#json('GET', '/api/category/tree'),
|
||||
|
||||
@@ -293,6 +293,10 @@ export class StorageManager extends ApiClient {
|
||||
const posterminalCache = createCache('GET /posterminal', () => this.#loadPosterminals());
|
||||
const supplierCache = createCache('GET /supplier', () => this.#loadSuppliers());
|
||||
const deliveryCache = createCache('GET /delivery', () => this.#loadDeliveries());
|
||||
const customergroupCache = createCache('GET /customergroup', () =>
|
||||
this.#loadCustomergroups(),
|
||||
);
|
||||
const entityCache = createCache('GET /entity', () => this.#loadEntities());
|
||||
|
||||
Object.defineProperties(this, {
|
||||
authMePromise: { get: () => authMeCache.promise },
|
||||
@@ -336,6 +340,16 @@ export class StorageManager extends ApiClient {
|
||||
/** Settled GET /delivery list, or undefined. */
|
||||
deliveries: { get: () => deliveryCache.value },
|
||||
|
||||
customergroupPromise: { get: () => customergroupCache.promise },
|
||||
updateCustomergroup: { value: customergroupCache.update },
|
||||
/** Settled GET /customergroup list, or undefined. */
|
||||
customergroups: { get: () => customergroupCache.value },
|
||||
|
||||
entityPromise: { get: () => entityCache.promise },
|
||||
updateEntity: { value: entityCache.update },
|
||||
/** Settled GET /entity list, or undefined. */
|
||||
entities: { get: () => entityCache.value },
|
||||
|
||||
/** Close and reopen GET /api/events (required after selected-company change). */
|
||||
reconnectEvents: { value: () => this.#reconnectEvents() },
|
||||
});
|
||||
@@ -468,6 +482,18 @@ export class StorageManager extends ApiClient {
|
||||
return requireArray(data.deliveries, 'deliveries');
|
||||
}
|
||||
|
||||
async #loadCustomergroups() {
|
||||
const data = await this.customergroup.list();
|
||||
requireObject(data, 'GET /api/customergroup');
|
||||
return requireArray(data.customergroups, 'customergroups');
|
||||
}
|
||||
|
||||
async #loadEntities() {
|
||||
const data = await this.entity.list();
|
||||
requireObject(data, 'GET /api/entity');
|
||||
return requireArray(data.entities, 'entities');
|
||||
}
|
||||
|
||||
async doSearch({ target, filter, offset, maxCount, onUpdate }) {
|
||||
const articles = await this.articleIndexPromise;
|
||||
const query = target.trim().toLowerCase();
|
||||
|
||||
130
src/api/index.js
130
src/api/index.js
@@ -599,6 +599,132 @@ export const delivery = {
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Company-scoped customer groups.
|
||||
* Shape: CustomerGroup = { id, name }
|
||||
*/
|
||||
export const customergroup = {
|
||||
/** GET /api/customergroup → { customergroups: CustomerGroup[] } */
|
||||
list() {
|
||||
return http('/api/customergroup');
|
||||
},
|
||||
|
||||
/**
|
||||
* POST /api/customergroup
|
||||
* Body: { name } — empty name ⇒ 400 Name required.
|
||||
* → 201 { customergroup: CustomerGroup }
|
||||
*/
|
||||
create(body) {
|
||||
return http('/api/customergroup', { method: 'POST', body });
|
||||
},
|
||||
|
||||
/**
|
||||
* PATCH /api/customergroup/:id
|
||||
* Body: { name }
|
||||
* → 200 { customergroup: CustomerGroup }
|
||||
*/
|
||||
update(id, body) {
|
||||
return http(`/api/customergroup/${id}`, { method: 'PATCH', body });
|
||||
},
|
||||
|
||||
/** DELETE /api/customergroup/:id → 204 · 409 Customer group in use */
|
||||
delete(id) {
|
||||
return http(`/api/customergroup/${id}`, { method: 'DELETE' });
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Company-scoped entities (customers / contacts in a customergroup).
|
||||
* Shape: Entity = { id, customergroupId, firstName, name, createdAt, updatedAt }
|
||||
*/
|
||||
export const entity = {
|
||||
/**
|
||||
* GET /api/entity → { entities: Entity[] }
|
||||
* Optional query: customergroupId
|
||||
*/
|
||||
list({ customergroupId } = {}) {
|
||||
const qs =
|
||||
customergroupId != null
|
||||
? `?customergroupId=${encodeURIComponent(customergroupId)}`
|
||||
: '';
|
||||
return http(`/api/entity${qs}`);
|
||||
},
|
||||
|
||||
/** GET /api/entity/:id → { entity: Entity } */
|
||||
get(id) {
|
||||
return http(`/api/entity/${id}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* POST /api/entity
|
||||
* Body: { customergroupId, name, firstName? }
|
||||
* → 201 { entity: Entity }
|
||||
*/
|
||||
create(body) {
|
||||
return http('/api/entity', { method: 'POST', body });
|
||||
},
|
||||
|
||||
/**
|
||||
* PATCH /api/entity/:id
|
||||
* Body: { name?, firstName? }
|
||||
* → 200 { entity: Entity }
|
||||
*/
|
||||
update(id, body) {
|
||||
return http(`/api/entity/${id}`, { method: 'PATCH', body });
|
||||
},
|
||||
|
||||
/** DELETE /api/entity/:id → 204 */
|
||||
delete(id) {
|
||||
return http(`/api/entity/${id}`, { method: 'DELETE' });
|
||||
},
|
||||
|
||||
/** GET /api/entity/:entityId/address → { addresses: EntityAddress[] } */
|
||||
listAddresses(entityId) {
|
||||
return http(`/api/entity/${entityId}/address`);
|
||||
},
|
||||
|
||||
/** POST /api/entity/:entityId/address → 201 { address } */
|
||||
createAddress(entityId, body) {
|
||||
return http(`/api/entity/${entityId}/address`, { method: 'POST', body });
|
||||
},
|
||||
|
||||
/** PATCH /api/entity/:entityId/address/:id → { address } */
|
||||
updateAddress(entityId, id, body) {
|
||||
return http(`/api/entity/${entityId}/address/${id}`, {
|
||||
method: 'PATCH',
|
||||
body,
|
||||
});
|
||||
},
|
||||
|
||||
/** DELETE /api/entity/:entityId/address/:id → 204 */
|
||||
deleteAddress(entityId, id) {
|
||||
return http(`/api/entity/${entityId}/address/${id}`, { method: 'DELETE' });
|
||||
},
|
||||
|
||||
/** GET /api/entity/:entityId/contact → { contacts: EntityContact[] } */
|
||||
listContacts(entityId) {
|
||||
return http(`/api/entity/${entityId}/contact`);
|
||||
},
|
||||
|
||||
/** POST /api/entity/:entityId/contact → 201 { contact } */
|
||||
createContact(entityId, body) {
|
||||
return http(`/api/entity/${entityId}/contact`, { method: 'POST', body });
|
||||
},
|
||||
|
||||
/** PATCH /api/entity/:entityId/contact/:id → { contact } */
|
||||
updateContact(entityId, id, body) {
|
||||
return http(`/api/entity/${entityId}/contact/${id}`, {
|
||||
method: 'PATCH',
|
||||
body,
|
||||
});
|
||||
},
|
||||
|
||||
/** DELETE /api/entity/:entityId/contact/:id → 204 */
|
||||
deleteContact(entityId, id) {
|
||||
return http(`/api/entity/${entityId}/contact/${id}`, { method: 'DELETE' });
|
||||
},
|
||||
};
|
||||
|
||||
export const company = {
|
||||
/** GET /api/company → { companies: [...] } */
|
||||
list() {
|
||||
@@ -774,9 +900,11 @@ export default {
|
||||
brand,
|
||||
category,
|
||||
company,
|
||||
customergroup,
|
||||
delivery,
|
||||
entity,
|
||||
posterminal,
|
||||
supplier,
|
||||
delivery,
|
||||
thumb,
|
||||
unit,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user