feat: nový stav "Doručeno" pro objednávky
CI / Generate TypeScript types (push) Successful in 10s
CI / Server unit tests (push) Successful in 26s
CI / Build server (push) Successful in 28s
CI / Build client (push) Successful in 42s
CI / Playwright E2E tests (push) Successful in 1m43s
CI / Build and push Docker image (push) Successful in 48s
CI / Notify (push) Successful in 1s
CI / Generate TypeScript types (push) Successful in 10s
CI / Server unit tests (push) Successful in 26s
CI / Build server (push) Successful in 28s
CI / Build client (push) Successful in 42s
CI / Playwright E2E tests (push) Successful in 1m43s
CI / Build and push Docker image (push) Successful in 48s
CI / Notify (push) Successful in 1s
This commit is contained in:
+36
-10
@@ -29,6 +29,26 @@ function findGroup(data: ClientData, id: string): OrderGroup | undefined {
|
||||
return data.groups?.find(g => g.id === id);
|
||||
}
|
||||
|
||||
/** České názvy stavů pro chybová hlášení. */
|
||||
const STATE_LABEL: Record<GroupState, string> = {
|
||||
[GroupState.OPEN]: 'otevřeno',
|
||||
[GroupState.LOCKED]: 'uzamčeno',
|
||||
[GroupState.ORDERED]: 'objednáno',
|
||||
[GroupState.DELIVERED]: 'doručeno',
|
||||
};
|
||||
|
||||
/** Stavy, ve kterých je objednávka již odeslána do podniku a nelze ji tedy upravovat. */
|
||||
function isSubmitted(state: GroupState): boolean {
|
||||
return state === GroupState.ORDERED || state === GroupState.DELIVERED;
|
||||
}
|
||||
|
||||
/** Ověří, že skupina není v odeslaném stavu (objednáno/doručeno), jinak vyhodí chybu. */
|
||||
function assertNotSubmitted(group: OrderGroup): void {
|
||||
if (isSubmitted(group.state)) {
|
||||
throw new Error(`Skupinu ve stavu "${STATE_LABEL[group.state]}" nelze upravovat`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vrátí seznam ISO dat (YYYY-MM-DD), pro která existuje alespoň jedna objednávková skupina.
|
||||
* Slouží ke zvýraznění dnů v date pickeru na stránce objednávání.
|
||||
@@ -100,7 +120,7 @@ export async function addGroupMember(login: string, groupId: string, targetLogin
|
||||
const data = await getExtraData(date);
|
||||
const group = findGroup(data, groupId);
|
||||
if (!group) throw new Error('Skupina nebyla nalezena');
|
||||
if (group.state === GroupState.ORDERED) throw new Error('Skupinu ve stavu "objednáno" nelze upravovat');
|
||||
assertNotSubmitted(group);
|
||||
if (login !== group.creatorLogin && login !== targetLogin) {
|
||||
throw new Error('Přidat jiného uživatele může pouze zakladatel');
|
||||
}
|
||||
@@ -116,7 +136,7 @@ export async function removeGroupMember(login: string, groupId: string, targetLo
|
||||
const data = await getExtraData(date);
|
||||
const group = findGroup(data, groupId);
|
||||
if (!group) throw new Error('Skupina nebyla nalezena');
|
||||
if (group.state === GroupState.ORDERED) throw new Error('Skupinu ve stavu "objednáno" nelze upravovat');
|
||||
assertNotSubmitted(group);
|
||||
if (login !== group.creatorLogin && login !== targetLogin) {
|
||||
throw new Error('Odebrat jiného uživatele může pouze zakladatel');
|
||||
}
|
||||
@@ -133,7 +153,7 @@ export async function updateGroupMember(login: string, groupId: string, targetLo
|
||||
const data = await getExtraData(date);
|
||||
const group = findGroup(data, groupId);
|
||||
if (!group) throw new Error('Skupina nebyla nalezena');
|
||||
if (group.state === GroupState.ORDERED) throw new Error('Skupinu ve stavu "objednáno" nelze upravovat');
|
||||
assertNotSubmitted(group);
|
||||
const isSelf = login === targetLogin;
|
||||
const isCreator = login === group.creatorLogin;
|
||||
if (!isSelf && !isCreator) throw new Error('Upravit jiného uživatele může pouze zakladatel');
|
||||
@@ -148,7 +168,8 @@ export async function updateGroupMember(login: string, groupId: string, targetLo
|
||||
const VALID_TRANSITIONS: Record<GroupState, GroupState[]> = {
|
||||
[GroupState.OPEN]: [GroupState.LOCKED],
|
||||
[GroupState.LOCKED]: [GroupState.OPEN, GroupState.ORDERED],
|
||||
[GroupState.ORDERED]: [GroupState.LOCKED],
|
||||
[GroupState.ORDERED]: [GroupState.LOCKED, GroupState.DELIVERED],
|
||||
[GroupState.DELIVERED]: [GroupState.ORDERED],
|
||||
};
|
||||
|
||||
function getCurrentHHMM(): string {
|
||||
@@ -162,7 +183,7 @@ export async function setGroupState(login: string, groupId: string, newState: Gr
|
||||
if (!group) throw new Error('Skupina nebyla nalezena');
|
||||
if (group.creatorLogin !== login) throw new Error('Stav může měnit pouze zakladatel');
|
||||
if (!VALID_TRANSITIONS[group.state].includes(newState)) {
|
||||
throw new Error(`Nelze přejít ze stavu "${group.state}" do stavu "${newState}"`);
|
||||
throw new Error(`Nelze přejít ze stavu "${STATE_LABEL[group.state]}" do stavu "${STATE_LABEL[newState]}"`);
|
||||
}
|
||||
if (newState === GroupState.ORDERED) {
|
||||
group.orderedAt = getCurrentHHMM();
|
||||
@@ -185,14 +206,19 @@ export async function setGroupState(login: string, groupId: string, newState: Gr
|
||||
return saveExtraData(data, date);
|
||||
}
|
||||
|
||||
export async function markGroupQrGenerated(login: string, groupId: string, date?: Date): Promise<void> {
|
||||
/**
|
||||
* Označí skupinu za vygenerovanou (blokuje opakované generování QR) a zároveň ji
|
||||
* překlopí do stavu "doručeno" — generování QR je poslední krok objednávky.
|
||||
*/
|
||||
export async function markGroupQrGenerated(login: string, groupId: string, date?: Date): Promise<ClientData> {
|
||||
const data = await getExtraData(date);
|
||||
const group = findGroup(data, groupId);
|
||||
if (!group) throw new Error('Skupina nebyla nalezena');
|
||||
if (group.creatorLogin !== login) throw new Error('QR kódy může generovat pouze zakladatel');
|
||||
if (group.state !== GroupState.ORDERED) throw new Error('QR kódy lze generovat pouze ve stavu "objednáno"');
|
||||
if (!isSubmitted(group.state)) throw new Error('QR kódy lze generovat pouze ve stavu "objednáno" nebo "doručeno"');
|
||||
group.qrGenerated = true;
|
||||
await saveExtraData(data, date);
|
||||
group.state = GroupState.DELIVERED;
|
||||
return saveExtraData(data, date);
|
||||
}
|
||||
|
||||
export async function markGroupMemberPaid(login: string, groupId: string, date?: Date): Promise<ClientData | null> {
|
||||
@@ -208,7 +234,7 @@ export async function updateGroupFees(login: string, groupId: string, fees?: num
|
||||
const group = findGroup(data, groupId);
|
||||
if (!group) throw new Error('Skupina nebyla nalezena');
|
||||
if (group.creatorLogin !== login) throw new Error('Poplatky může měnit pouze zakladatel');
|
||||
if (group.state === GroupState.ORDERED) throw new Error('Skupinu ve stavu "objednáno" nelze upravovat');
|
||||
assertNotSubmitted(group);
|
||||
if (fees !== undefined) group.fees = fees > 0 ? fees : undefined;
|
||||
if (shipping !== undefined) group.shipping = shipping > 0 ? shipping : undefined;
|
||||
if (tip !== undefined) group.tip = tip > 0 ? tip : undefined;
|
||||
@@ -238,7 +264,7 @@ export async function setGroupTracking(login: string, groupId: string, shareUrl?
|
||||
group.trackingOrderState = undefined;
|
||||
group.trackingCourierState = undefined;
|
||||
} else {
|
||||
if (group.state !== GroupState.ORDERED) throw new Error('Sledování objednávky lze nastavit pouze ve stavu "objednáno"');
|
||||
if (!isSubmitted(group.state)) throw new Error('Sledování objednávky lze nastavit pouze ve stavu "objednáno" nebo "doručeno"');
|
||||
const tracking = extractTracking(shareUrl);
|
||||
if (!tracking) throw new Error('Neplatný odkaz na sledování objednávky');
|
||||
if (tracking.code !== group.trackingCode || tracking.provider !== group.trackingProvider) {
|
||||
|
||||
Reference in New Issue
Block a user