1040 lines
31 KiB
Vue
1040 lines
31 KiB
Vue
<script>
|
|
import Swal from "sweetalert2";
|
|
import {ObjectsGlobal} from "@/components/session/token/SessionUser/Objects/ObjectsGlobal.vue";
|
|
import {SessionUser} from "@/components/session/token/SessionUser.vue";
|
|
import AssignDraftOrderCustomerModal from "@/components/displays/modals/AssignDraftOrderCustomerModal.vue";
|
|
import { authenticatedRequest } from "@/components/session/authenticatedRequest.vue";
|
|
import { editOrderItem, getOrderItems } from "@/components/shop/OrdersItems.vue";
|
|
import {createApp} from "vue";
|
|
import i18n from '@/i18n';
|
|
import { dispatchNavigationCountRefresh } from "@/components/models/navigation/items/navigationCountEvents.js";
|
|
|
|
const t = (key) => i18n.global.t(key);
|
|
|
|
const getProtectedDeletePayload = (error) => {
|
|
const payload = error?.response?.data?.data;
|
|
if (error?.response?.status !== 409 || payload?.requires_confirmation !== true) {
|
|
return null;
|
|
}
|
|
return payload;
|
|
};
|
|
|
|
const formatDeleteProtectionReason = (reason) => {
|
|
switch (reason) {
|
|
case "completed":
|
|
return "ordren er fuldført";
|
|
case "order_items":
|
|
return "ordren har varelinjer";
|
|
case "attachments":
|
|
return "ordren har vedhæftninger";
|
|
default:
|
|
return String(reason || "").replace(/_/g, " ");
|
|
}
|
|
};
|
|
|
|
const showProtectedOrderDeleteConfirmation = async (id, protectionPayload, onAfterSubmit = null) => {
|
|
const orderId = String(id);
|
|
const reasons = Array.isArray(protectionPayload?.protected_reasons)
|
|
? protectionPayload.protected_reasons.map(formatDeleteProtectionReason).filter(Boolean)
|
|
: [];
|
|
const reasonText = reasons.length > 0 ? reasons.join(", ") : "ordren indeholder gemte data";
|
|
|
|
const result = await Swal.fire({
|
|
title: `Bekræft sletning af ordre #${orderId}`,
|
|
html: `
|
|
<p>Ordren kan stadig slettes, men kræver ekstra bekræftelse fordi ${reasonText}.</p>
|
|
<p>Skriv <strong>${orderId}</strong> for at slette ordren.</p>
|
|
`,
|
|
input: "text",
|
|
inputAttributes: {
|
|
autocapitalize: "off",
|
|
autocomplete: "off",
|
|
},
|
|
icon: "warning",
|
|
showCancelButton: true,
|
|
confirmButtonText: "Slet ordre",
|
|
cancelButtonText: "Fortryd",
|
|
showLoaderOnConfirm: true,
|
|
didOpen: () => {
|
|
const confirmButton = Swal.getConfirmButton();
|
|
const input = Swal.getInput();
|
|
input?.setAttribute("data-testid", "protected-order-delete-input");
|
|
const updateConfirmState = () => {
|
|
if (confirmButton) {
|
|
confirmButton.disabled = String(input?.value ?? "").trim() !== orderId;
|
|
}
|
|
};
|
|
|
|
input?.addEventListener("input", updateConfirmState);
|
|
updateConfirmState();
|
|
},
|
|
preConfirm: async (value) => {
|
|
if (String(value ?? "").trim() !== orderId) {
|
|
Swal.showValidationMessage("Ordre-id matcher ikke");
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
return await Orders.delete.single(id, { confirmed: true });
|
|
} catch (error) {
|
|
Swal.showValidationMessage(SessionUser.functions.parseErrorMessage(error) || "Ordren kunne ikke slettes");
|
|
return false;
|
|
}
|
|
},
|
|
allowOutsideClick: () => !Swal.isLoading(),
|
|
});
|
|
|
|
if (!result.isConfirmed) {
|
|
return null;
|
|
}
|
|
|
|
if (onAfterSubmit !== null) {
|
|
onAfterSubmit(result.value);
|
|
}
|
|
|
|
return result.value;
|
|
};
|
|
|
|
const deleteOrderWithProtectedConfirmation = async (id, onAfterSubmit = null) => {
|
|
try {
|
|
const response = await Orders.delete.single(id);
|
|
if (onAfterSubmit !== null) {
|
|
onAfterSubmit(response);
|
|
}
|
|
return response;
|
|
} catch (error) {
|
|
const protectedDeletePayload = getProtectedDeletePayload(error);
|
|
if (!protectedDeletePayload) {
|
|
throw error;
|
|
}
|
|
return showProtectedOrderDeleteConfirmation(id, protectedDeletePayload, onAfterSubmit);
|
|
}
|
|
};
|
|
|
|
const mountOrderCustomerAssignmentModal = ({
|
|
order,
|
|
title,
|
|
subtitle,
|
|
submitLabel,
|
|
errorMessageText,
|
|
newCollectionDescription,
|
|
onAssigned = null,
|
|
}) => {
|
|
const host = document.createElement("div");
|
|
host.dataset.testid = "change-customer-assignment-host";
|
|
document.body.appendChild(host);
|
|
|
|
let isDisposed = false;
|
|
let app = null;
|
|
|
|
const dispose = () => {
|
|
if (isDisposed) {
|
|
return;
|
|
}
|
|
|
|
isDisposed = true;
|
|
app?.unmount?.();
|
|
host.remove();
|
|
};
|
|
|
|
app = createApp(AssignDraftOrderCustomerModal, {
|
|
order,
|
|
title,
|
|
subtitle,
|
|
submitLabel,
|
|
errorMessageText,
|
|
newCollectionDescription,
|
|
onClose: () => dispose(),
|
|
onAssigned: async (response) => {
|
|
try {
|
|
if (typeof onAssigned === "function") {
|
|
await onAssigned(response);
|
|
}
|
|
} finally {
|
|
dispose();
|
|
}
|
|
},
|
|
});
|
|
|
|
app.use(i18n);
|
|
app.mount(host);
|
|
|
|
return dispose;
|
|
}
|
|
|
|
|
|
|
|
const showChangeOrderCustomerForm = async (id, onAfterSubmit = null) => {
|
|
const normalizedOrderId = normalizePositiveInteger(id);
|
|
if (!normalizedOrderId) {
|
|
return;
|
|
}
|
|
|
|
mountOrderCustomerAssignmentModal({
|
|
order: {
|
|
id: normalizedOrderId,
|
|
department_id: null,
|
|
invoice_collection_id: null,
|
|
},
|
|
title: t("admin.pos.settings_wheel.change_customer"),
|
|
subtitle: `Vælg kunde og fakturasamling for at flytte ordre #${normalizedOrderId} til den valgte kunde.`,
|
|
submitLabel: t("admin.pos.settings_wheel.change_customer"),
|
|
errorMessageText: "Der opstod en fejl under ændring af kunde.",
|
|
newCollectionDescription: "Oprettet fra kundeskift",
|
|
onAssigned: async (response) => {
|
|
if (typeof onAfterSubmit === 'function') {
|
|
await onAfterSubmit(response);
|
|
return;
|
|
}
|
|
|
|
window.location.reload();
|
|
}
|
|
});
|
|
}
|
|
|
|
const showChangeOrderInvoiceCollectionForm = async (id, onAfterSubmit = null) => {
|
|
let customer_number = null;
|
|
// Get the customer number from the order
|
|
await SessionUser.objects.orders.functions.get_customer_id(id).then((response) => {
|
|
customer_number = response;
|
|
console.log("Customer number:", customer_number);
|
|
}).catch((error) => {
|
|
console.error(error);
|
|
});
|
|
if (!customer_number) {
|
|
console.error("Ingen kunde fundet");
|
|
return;
|
|
}
|
|
// Select the invoice collection
|
|
await SessionUser.objects.collectedOrderInvoices.functions.showInvoiceCollectionPickerForm(
|
|
customer_number,
|
|
async (invoice_collection_id) => {
|
|
if (!invoice_collection_id) {
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Ingen faktura samling valgt',
|
|
timer: 2000,
|
|
});
|
|
return;
|
|
}
|
|
// Handle the invoice collection selection here
|
|
console.log("Selected invoice collection:", invoice_collection_id);
|
|
console.log("Changing invoice collection for order:", id, " customer:", customer_number);
|
|
console.log("New invoice collection:", invoice_collection_id);
|
|
try {
|
|
const response = await SessionUser.objects.orders.set.invoice_collection_id(
|
|
parseInt(id, 10),
|
|
parseInt(invoice_collection_id, 10)
|
|
);
|
|
console.log("Invoice collection changed successfully:", response);
|
|
Swal.fire({
|
|
icon: 'success',
|
|
title: 'Faktura samling ændret',
|
|
timer: 2000,
|
|
});
|
|
if (typeof onAfterSubmit === 'function') {
|
|
await onAfterSubmit(response);
|
|
}
|
|
} catch (error) {
|
|
console.error("Error changing invoice collection:", error);
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Fejl ved ændring af faktura samling',
|
|
timer: 2000,
|
|
});
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
const normalizePositiveInteger = (value) => {
|
|
const parsedValue = Number.parseInt(value, 10);
|
|
return Number.isInteger(parsedValue) && parsedValue > 0 ? parsedValue : null;
|
|
};
|
|
|
|
const refreshDraftNavigationCount = () => {
|
|
dispatchNavigationCountRefresh();
|
|
};
|
|
|
|
const getFinalProductPriceForCustomer = async (productId, departmentId, customerId) => {
|
|
const normalizedProductId = normalizePositiveInteger(productId);
|
|
const normalizedDepartmentId = normalizePositiveInteger(departmentId);
|
|
const normalizedCustomerId = normalizePositiveInteger(customerId);
|
|
|
|
if (!normalizedProductId || !normalizedDepartmentId || !normalizedCustomerId) {
|
|
throw new Error("Invalid repricing context");
|
|
}
|
|
|
|
const response = await authenticatedRequest("/products", "GET", {
|
|
id: normalizedProductId,
|
|
department_id: normalizedDepartmentId,
|
|
customer_id: normalizedCustomerId,
|
|
final_price: "true",
|
|
});
|
|
|
|
const resolvedPrice = Number.parseInt(response?.data?.data?.price, 10);
|
|
if (!Number.isFinite(resolvedPrice)) {
|
|
throw new Error(`Unable to resolve price for product ${normalizedProductId}`);
|
|
}
|
|
|
|
return resolvedPrice;
|
|
};
|
|
|
|
const recalculateOrderItemPricesForCustomer = async ({ order_id, department_id, customer_id }) => {
|
|
const normalizedOrderId = normalizePositiveInteger(order_id);
|
|
const normalizedDepartmentId = normalizePositiveInteger(department_id);
|
|
const normalizedCustomerId = normalizePositiveInteger(customer_id);
|
|
|
|
if (!normalizedOrderId || !normalizedDepartmentId || !normalizedCustomerId) {
|
|
throw new Error("Invalid order repricing context");
|
|
}
|
|
|
|
const response = await getOrderItems(normalizedOrderId);
|
|
const orderItems = Array.isArray(response?.data?.data) ? response.data.data : [];
|
|
const uniqueProductIds = [...new Set(
|
|
orderItems
|
|
.map((item) => normalizePositiveInteger(item?.product_id))
|
|
.filter((value) => value !== null)
|
|
)];
|
|
|
|
if (uniqueProductIds.length === 0) {
|
|
return {
|
|
items: orderItems,
|
|
updated_count: 0,
|
|
};
|
|
}
|
|
|
|
const priceEntries = await Promise.all(
|
|
uniqueProductIds.map(async (productId) => {
|
|
const finalPrice = await getFinalProductPriceForCustomer(productId, normalizedDepartmentId, normalizedCustomerId);
|
|
return [productId, finalPrice];
|
|
})
|
|
);
|
|
|
|
const finalPriceMap = new Map(priceEntries);
|
|
const updateRequests = orderItems
|
|
.map((item) => {
|
|
const normalizedItemId = normalizePositiveInteger(item?.id);
|
|
const normalizedProductId = normalizePositiveInteger(item?.product_id);
|
|
if (!normalizedItemId || !normalizedProductId || !finalPriceMap.has(normalizedProductId)) {
|
|
return null;
|
|
}
|
|
|
|
return editOrderItem(
|
|
normalizedItemId,
|
|
finalPriceMap.get(normalizedProductId),
|
|
item?.notes ?? "",
|
|
item?.reference ?? "",
|
|
normalizePositiveInteger(item?.quantity) ?? 1
|
|
);
|
|
})
|
|
.filter(Boolean);
|
|
|
|
await Promise.all(updateRequests);
|
|
|
|
return {
|
|
items: orderItems,
|
|
updated_count: updateRequests.length,
|
|
};
|
|
};
|
|
|
|
const assignDraftOrderCustomer = async ({
|
|
order_id,
|
|
customer_id,
|
|
invoice_collection_id,
|
|
department_id = null,
|
|
recalculate_prices = true,
|
|
}) => {
|
|
const normalizedOrderId = normalizePositiveInteger(order_id);
|
|
const normalizedCustomerId = normalizePositiveInteger(customer_id);
|
|
const normalizedInvoiceCollectionId = normalizePositiveInteger(invoice_collection_id);
|
|
|
|
if (!normalizedOrderId || !normalizedCustomerId || !normalizedInvoiceCollectionId) {
|
|
throw new Error("Order, customer and invoice collection are required");
|
|
}
|
|
|
|
const resolvedDepartmentId = normalizePositiveInteger(department_id)
|
|
?? await SessionUser.objects.orders.functions.get_department_id(normalizedOrderId);
|
|
|
|
const customerResponse = await SessionUser.objects.orders.set.customer_id(
|
|
normalizedOrderId,
|
|
normalizedCustomerId
|
|
);
|
|
|
|
const invoiceCollectionResponse = await SessionUser.objects.orders.set.invoice_collection_id(
|
|
normalizedOrderId,
|
|
normalizedInvoiceCollectionId
|
|
);
|
|
|
|
let repricingResponse = null;
|
|
if (recalculate_prices) {
|
|
repricingResponse = await recalculateOrderItemPricesForCustomer({
|
|
order_id: normalizedOrderId,
|
|
department_id: resolvedDepartmentId,
|
|
customer_id: normalizedCustomerId,
|
|
});
|
|
}
|
|
|
|
return {
|
|
customerResponse,
|
|
invoiceCollectionResponse,
|
|
repricingResponse,
|
|
customer_id: normalizedCustomerId,
|
|
invoice_collection_id: normalizedInvoiceCollectionId,
|
|
department_id: resolvedDepartmentId,
|
|
};
|
|
};
|
|
|
|
/**
|
|
* The Orders object
|
|
*/
|
|
export const Orders = {
|
|
get meta() {
|
|
return {
|
|
title: t('objects.orders.title'),
|
|
icon: "fas fa-list",
|
|
description: t('objects.orders.description'),
|
|
endpoint: "/orders",
|
|
labels: {
|
|
single: t('objects.orders.single'),
|
|
multiple: t('objects.orders.multiple'),
|
|
entries: t('objects.orders.entries'),
|
|
}
|
|
};
|
|
},
|
|
get columns() {
|
|
return {
|
|
id: {
|
|
label: t('objects.columns.id'),
|
|
type: "number",
|
|
sortable: true,
|
|
creation: {
|
|
required: false
|
|
}
|
|
},
|
|
customer_id: {
|
|
label: t('objects.columns.customer'),
|
|
type: "number",
|
|
sortable: true,
|
|
creation: {
|
|
required: true
|
|
}
|
|
},
|
|
cashier_id: {
|
|
label: t('objects.orders.columns.cashier'),
|
|
type: "number",
|
|
sortable: true,
|
|
creation: {
|
|
required: false
|
|
}
|
|
},
|
|
department_id: {
|
|
label: t('objects.columns.department'),
|
|
type: "select",
|
|
sortable: true,
|
|
creation: {
|
|
required: true
|
|
},
|
|
options: async () => {
|
|
return SessionUser.objects.departments.get.all();
|
|
}
|
|
},
|
|
reference: {
|
|
label: t('common.reference'),
|
|
type: "string",
|
|
sortable: true,
|
|
creation: {
|
|
required: false
|
|
}
|
|
},
|
|
reg_1: {
|
|
label: t('objects.orders.columns.license_plate'),
|
|
type: "string",
|
|
sortable: true,
|
|
creation: {
|
|
required: true
|
|
}
|
|
},
|
|
reg_2: {
|
|
label: t('objects.orders.columns.reg_2'),
|
|
type: "string",
|
|
sortable: true,
|
|
creation: {
|
|
required: false
|
|
}
|
|
},
|
|
reg_3: {
|
|
label: t('objects.orders.columns.reg_3'),
|
|
type: "string",
|
|
sortable: true,
|
|
creation: {
|
|
required: false
|
|
}
|
|
},
|
|
notes: {
|
|
label: t('objects.columns.notes'),
|
|
type: "string",
|
|
sortable: true,
|
|
creation: {
|
|
required: false
|
|
}
|
|
},
|
|
invoice_collection_id: {
|
|
label: t('common.invoice'),
|
|
type: "number",
|
|
sortable: true,
|
|
creation: {
|
|
required: false
|
|
}
|
|
},
|
|
booking_id: {
|
|
label: t('objects.columns.booking'),
|
|
type: "number",
|
|
sortable: true,
|
|
creation: {
|
|
required: false
|
|
}
|
|
},
|
|
wash_id: {
|
|
label: t('objects.orders.columns.wash_id'),
|
|
type: "string",
|
|
sortable: true,
|
|
creation: {
|
|
required: false
|
|
}
|
|
},
|
|
lane: {
|
|
label: t('objects.orders.columns.lane'),
|
|
type: "string",
|
|
sortable: true,
|
|
creation: {
|
|
required: false
|
|
}
|
|
},
|
|
po: {
|
|
label: t('objects.orders.columns.po'),
|
|
type: "string",
|
|
sortable: true,
|
|
creation: {
|
|
required: false
|
|
}
|
|
},
|
|
safety_seal: {
|
|
label: t('admin.pos.safety_seal'),
|
|
type: "string",
|
|
sortable: true,
|
|
creation: {
|
|
required: false
|
|
}
|
|
},
|
|
created_at: {
|
|
label: t('common.date'),
|
|
type: "datetime",
|
|
sortable: true,
|
|
creation: {
|
|
required: false
|
|
}
|
|
},
|
|
include_in_invoice: {
|
|
label: t('pos.order.include_in_invoice'),
|
|
type: "select",
|
|
sortable: true,
|
|
creation: {
|
|
required: false
|
|
},
|
|
options: async () => {
|
|
return [
|
|
{ id: 'use_department', name: t('pos.order.invoice_override.use_department') },
|
|
{ id: 'include', name: t('pos.order.invoice_override.include') },
|
|
{ id: 'exclude', name: t('pos.order.invoice_override.exclude') },
|
|
];
|
|
}
|
|
},
|
|
completed_at: {
|
|
label: t('objects.columns.completed'),
|
|
type: "date",
|
|
sortable: true,
|
|
creation: {
|
|
required: false
|
|
}
|
|
},
|
|
};
|
|
},
|
|
add: async (customer_id, cashier_id, department_id, reference, reg_1, reg_2, reg_3, notes, invoice_collection_id) => {
|
|
const response = await ObjectsGlobal.add.object(
|
|
Orders.meta.endpoint,
|
|
{
|
|
customer_id: parseInt(customer_id),
|
|
cashier_id: parseInt(cashier_id),
|
|
department_id: parseInt(department_id),
|
|
reference: reference === null ? "" : reference,
|
|
reg_1: reg_1,
|
|
reg_2: reg_2,
|
|
reg_3: reg_3,
|
|
notes: notes === null ? "" : notes,
|
|
invoice_collection_id: parseInt(invoice_collection_id),
|
|
}
|
|
);
|
|
refreshDraftNavigationCount();
|
|
return response;
|
|
},
|
|
set: {
|
|
customer_id: async (id, customer_id) => {
|
|
const response = await ObjectsGlobal.set.column(
|
|
Orders.meta.endpoint,
|
|
id,
|
|
"customer_id",
|
|
parseInt(customer_id)
|
|
);
|
|
refreshDraftNavigationCount();
|
|
return response;
|
|
},
|
|
cashier_id: async (id, cashier_id) => {
|
|
return ObjectsGlobal.set.column(
|
|
Orders.meta.endpoint,
|
|
id,
|
|
"cashier_id",
|
|
parseInt(cashier_id)
|
|
)
|
|
},
|
|
department_id: async (id, department_id) => {
|
|
return ObjectsGlobal.set.column(
|
|
Orders.meta.endpoint,
|
|
id,
|
|
"department_id",
|
|
parseInt(department_id)
|
|
)
|
|
},
|
|
reference: async (id, reference) => {
|
|
return ObjectsGlobal.set.column(
|
|
Orders.meta.endpoint,
|
|
id,
|
|
"reference",
|
|
reference
|
|
)
|
|
},
|
|
reg_1: async (id, reg_1) => {
|
|
return ObjectsGlobal.set.column(
|
|
Orders.meta.endpoint,
|
|
id,
|
|
"reg_1",
|
|
reg_1
|
|
)
|
|
},
|
|
reg_2: async (id, reg_2) => {
|
|
return ObjectsGlobal.set.column(
|
|
Orders.meta.endpoint,
|
|
id,
|
|
"reg_2",
|
|
reg_2
|
|
)
|
|
},
|
|
reg_3: async (id, reg_3) => {
|
|
return ObjectsGlobal.set.column(
|
|
Orders.meta.endpoint,
|
|
id,
|
|
"reg_3",
|
|
reg_3
|
|
)
|
|
},
|
|
notes: async (id, notes) => {
|
|
return ObjectsGlobal.set.column(
|
|
Orders.meta.endpoint,
|
|
id,
|
|
"notes",
|
|
notes
|
|
)
|
|
},
|
|
invoice_collection_id: async (id, invoice_collection_id) => {
|
|
return ObjectsGlobal.set.column(
|
|
Orders.meta.endpoint,
|
|
id,
|
|
"invoice_collection_id",
|
|
parseInt(invoice_collection_id)
|
|
)
|
|
},
|
|
booking_id: async (id, booking_id) => {
|
|
return ObjectsGlobal.set.column(
|
|
Orders.meta.endpoint,
|
|
id,
|
|
"booking_id",
|
|
booking_id
|
|
)
|
|
},
|
|
wash_id: async (id, wash_id) => {
|
|
return ObjectsGlobal.set.column(
|
|
Orders.meta.endpoint,
|
|
id,
|
|
"wash_id",
|
|
wash_id
|
|
)
|
|
},
|
|
lane: async (id, lane) => {
|
|
return ObjectsGlobal.set.column(
|
|
Orders.meta.endpoint,
|
|
id,
|
|
"lane",
|
|
lane
|
|
)
|
|
},
|
|
po: async (id, po) => {
|
|
return ObjectsGlobal.set.column(
|
|
Orders.meta.endpoint,
|
|
id,
|
|
"po",
|
|
po
|
|
)
|
|
},
|
|
safety_seal: async (id, safety_seal) => {
|
|
return ObjectsGlobal.set.column(
|
|
Orders.meta.endpoint,
|
|
id,
|
|
"safety_seal",
|
|
safety_seal
|
|
)
|
|
},
|
|
created_at: async (id, created_at) => {
|
|
return ObjectsGlobal.set.column(
|
|
Orders.meta.endpoint,
|
|
id,
|
|
"created_at",
|
|
created_at
|
|
)
|
|
},
|
|
include_in_invoice: async (id, include_in_invoice) => {
|
|
const normalizedValue = include_in_invoice === 'include'
|
|
? true
|
|
: include_in_invoice === 'exclude'
|
|
? false
|
|
: null;
|
|
return ObjectsGlobal.set.column(
|
|
Orders.meta.endpoint,
|
|
id,
|
|
"include_in_invoice",
|
|
normalizedValue
|
|
)
|
|
},
|
|
completed_at: async (id, completed_at) => {
|
|
return ObjectsGlobal.set.column(
|
|
Orders.meta.endpoint,
|
|
id,
|
|
"completed_at",
|
|
completed_at
|
|
)
|
|
},
|
|
},
|
|
get: {
|
|
all: async () => {
|
|
return ObjectsGlobal.get.objects(Orders.meta.endpoint);
|
|
},
|
|
single: async (id) => {
|
|
return ObjectsGlobal.get.object('/order', id);
|
|
},
|
|
multiple: async (ids) => {
|
|
return ObjectsGlobal.get.objectsByIds('/order', ids);
|
|
},
|
|
list: async (optionsObject = {filters: {}, pagination: {page: 1, limit: 100, order: 'id:DESC'}}) => {
|
|
return ObjectsGlobal.get.list(Orders.meta.endpoint, optionsObject);
|
|
},
|
|
},
|
|
delete: {
|
|
single: async (id, optionsObject = null) => {
|
|
const response = optionsObject
|
|
? await ObjectsGlobal.delete.object(Orders.meta.endpoint, id, optionsObject)
|
|
: await ObjectsGlobal.delete.object(Orders.meta.endpoint, id);
|
|
refreshDraftNavigationCount();
|
|
return response;
|
|
},
|
|
},
|
|
functions: {
|
|
/**
|
|
* Mark the order as completed
|
|
* @param id
|
|
* @returns {Promise<void>}
|
|
*/
|
|
mark_as_completed: async (id) => {
|
|
return SessionUser.request(
|
|
Orders.meta.endpoint + "/mark_as_completed",
|
|
"POST",
|
|
{
|
|
id: id
|
|
},
|
|
)
|
|
},
|
|
/**
|
|
* Get the order department id
|
|
* @param id
|
|
*/
|
|
get_department_id: async (id) => {
|
|
return SessionUser.request(
|
|
'/order',
|
|
'GET',
|
|
{
|
|
id: id
|
|
}
|
|
).then((response) => {
|
|
//console.log(response.data.data.department_id);
|
|
return parseInt(response.data.data.department_id);
|
|
}).catch((error) => {
|
|
console.error(error);
|
|
});
|
|
},
|
|
/**
|
|
* Show deletion confirmation modal
|
|
* @param id
|
|
* @param onAfterSubmit
|
|
*/
|
|
showDeleteConfirmationModal: (id, onAfterSubmit = null) => {
|
|
return Swal.fire({
|
|
title: `Fjern ${Orders.meta.labels.single}?`,
|
|
text: ObjectsGlobal.language.confirm_delete_message,
|
|
showCancelButton: true,
|
|
showConfirmButton: true,
|
|
confirmButtonText: ObjectsGlobal.language.confirm_delete,
|
|
cancelButtonText: ObjectsGlobal.language.cancel,
|
|
icon: "warning",
|
|
}).then((result) => {
|
|
if (!result.isConfirmed) {
|
|
return null;
|
|
}
|
|
return deleteOrderWithProtectedConfirmation(id, onAfterSubmit);
|
|
});
|
|
},
|
|
deleteWithConfirmation: async (id, onAfterSubmit = null) => {
|
|
return deleteOrderWithProtectedConfirmation(id, onAfterSubmit);
|
|
},
|
|
/**
|
|
* Get the order customer number
|
|
* @param id (order id)
|
|
*/
|
|
get_customer_id: async (id) => {
|
|
return SessionUser.request(
|
|
'/order',
|
|
'GET',
|
|
{
|
|
id: id
|
|
}
|
|
).then((response) => {
|
|
//console.log(response.data.data.customer_id);
|
|
return parseInt(response.data.data.customer_id);
|
|
}).catch((error) => {
|
|
console.error(error);
|
|
});
|
|
},
|
|
/**
|
|
* Change the order customer
|
|
* @param id (order id)
|
|
* @param customer_id (e-conomic customer number)
|
|
*/
|
|
change_customer: async (id, customer_id) => {
|
|
return SessionUser.objects.orders.set.customer_id(id, customer_id);
|
|
},
|
|
/**
|
|
* Show the change customer form
|
|
* @param id (order id)
|
|
*/
|
|
showChangeCustomerForm: showChangeOrderCustomerForm,
|
|
assignDraftCustomer: assignDraftOrderCustomer,
|
|
/**
|
|
* Show the change invoice collection form
|
|
* @param id (order id)
|
|
*/
|
|
showChangeInvoiceCollectionForm: showChangeOrderInvoiceCollectionForm,
|
|
/**
|
|
* Fetch attachments for the order
|
|
* @param id (order id)
|
|
*/
|
|
fetchAttachments: async (id) => {
|
|
return SessionUser.request(
|
|
Orders.meta.endpoint + "/attachments",
|
|
"GET",
|
|
{
|
|
id: id
|
|
}
|
|
).then((response) => {
|
|
return response.data.data;
|
|
}).catch((error) => {
|
|
console.error(error);
|
|
throw error;
|
|
});
|
|
},
|
|
/**
|
|
* Delete an attachment from the order
|
|
* @param id (order id)
|
|
* @param attachment_id (attachment id)
|
|
*/
|
|
removeAttachment: async (id, attachment_id) => {
|
|
return SessionUser.request(
|
|
Orders.meta.endpoint + "/attachments",
|
|
"DELETE",
|
|
{
|
|
order_id: id,
|
|
attachment_id: attachment_id
|
|
}
|
|
).then((response) => {
|
|
return response.data;
|
|
}).catch((error) => {
|
|
console.error(error);
|
|
});
|
|
},
|
|
/**
|
|
* Upload an attachment to the order
|
|
* @param id (order id)
|
|
* @param filename (filename)
|
|
* @param filedata (filedata as base64)
|
|
*/
|
|
uploadAttachment: async (id, filename, filedata) => {
|
|
return SessionUser.request(
|
|
Orders.meta.endpoint + "/attachments/upload",
|
|
"POST",
|
|
{
|
|
order_id: id,
|
|
file_name: filename,
|
|
base64_file: filedata
|
|
}
|
|
).then((response) => {
|
|
return response.data.data;
|
|
}).catch((error) => {
|
|
console.error(error);
|
|
});
|
|
},
|
|
/**
|
|
* Generate a link, to download an attachment from the order
|
|
* @param id (order id)
|
|
* @param attachment_id (attachment id)
|
|
* @param autoOpen
|
|
*/
|
|
downloadAttachment: async (id, attachment_id, autoOpen = false) => {
|
|
return SessionUser.request(
|
|
Orders.meta.endpoint + "/attachments/download",
|
|
"GET",
|
|
{
|
|
order_id: id,
|
|
attachment_id: attachment_id
|
|
}
|
|
).then((response) => {
|
|
const downloadLink = response.data.data.download_link;
|
|
if (autoOpen) {
|
|
// Open the download link in a new tab
|
|
//window.open(downloadLink, '_blank');
|
|
window.open(downloadLink, '_blank', 'noopener,noreferrer');
|
|
}
|
|
return response.data.data.download_link;
|
|
}).catch((error) => {
|
|
console.error(error);
|
|
});
|
|
},
|
|
showAttachWashCertificateForm(order_id, onAfterSubmit = null) {
|
|
const normalizedOrderId = Number.parseInt(order_id, 10);
|
|
if (!Number.isInteger(normalizedOrderId) || normalizedOrderId <= 0) {
|
|
return Promise.resolve(false);
|
|
}
|
|
|
|
return Swal.fire({
|
|
title: t('admin.pos.generate_wash_certificate'),
|
|
text: t('admin.pos.enter_safety_seal_number'),
|
|
input: 'text',
|
|
inputLabel: t('admin.pos.safety_seal'),
|
|
showCancelButton: true,
|
|
confirmButtonText: t('admin.pos.generate_wash_certificate'),
|
|
cancelButtonText: t('admin.pos.cancel'),
|
|
preConfirm: (safety_seal) => {
|
|
const normalizedSafetySeal = typeof safety_seal === 'string'
|
|
? safety_seal.trim()
|
|
: safety_seal;
|
|
|
|
return SessionUser.request(
|
|
'/order/wash-certificate',
|
|
'POST',
|
|
{
|
|
id: normalizedOrderId,
|
|
safety_seal: normalizedSafetySeal
|
|
}
|
|
).then((response) => {
|
|
return response.data.data;
|
|
}).catch((error) => {
|
|
console.error(error);
|
|
const parsedError = SessionUser.functions.parseErrorMessage(error);
|
|
const errorMessage = typeof parsedError === 'string' ? parsedError : '';
|
|
Swal.showValidationMessage([
|
|
t('admin.pos.wash_certificate_generation_error'),
|
|
errorMessage,
|
|
].filter(Boolean).join(': '));
|
|
});
|
|
},
|
|
heightAuto: false,
|
|
}).then(async (result) => {
|
|
if (!result.isConfirmed || !result.value) {
|
|
return result;
|
|
}
|
|
|
|
if (typeof onAfterSubmit === 'function') {
|
|
try {
|
|
await onAfterSubmit(result.value);
|
|
} catch (error) {
|
|
console.error('Error after attaching wash certificate:', error);
|
|
}
|
|
}
|
|
|
|
const alreadyExisted = Boolean(result.value.already_existed);
|
|
await Swal.fire({
|
|
title: alreadyExisted
|
|
? t('admin.pos.settings_wheel.attach_wash_certificate')
|
|
: t('admin.pos.generate_wash_certificate'),
|
|
text: alreadyExisted
|
|
? t('admin.pos.wash_certificate_already_attached')
|
|
: t('admin.pos.wash_certificate_attached'),
|
|
icon: alreadyExisted ? 'info' : 'success',
|
|
showConfirmButton: false,
|
|
timer: 2000,
|
|
heightAuto: false,
|
|
});
|
|
|
|
return result.value;
|
|
});
|
|
}
|
|
},
|
|
/**
|
|
* Show the create object form
|
|
* @param onAfterSubmit
|
|
* @returns {Promise<SweetAlertResult<Awaited<any>>>}
|
|
*/
|
|
showCreateObjectForm: (onAfterSubmit = null) => {
|
|
return ObjectsGlobal.showCreateObjectForm(Orders, onAfterSubmit);
|
|
},
|
|
/**
|
|
* Show the edit object field form
|
|
* @param id
|
|
* @param column
|
|
* @param value
|
|
* @param onAfterSubmit
|
|
* @returns {Promise<SweetAlertResult<Awaited<any>>>}
|
|
*/
|
|
showEditObjectFieldForm: (id, column, value, onAfterSubmit = null) => {
|
|
const normalizedValue = column === 'include_in_invoice'
|
|
? (value === true ? 'include' : value === false ? 'exclude' : 'use_department')
|
|
: value;
|
|
return ObjectsGlobal.showEditObjectFieldForm(
|
|
Orders,
|
|
id,
|
|
column,
|
|
normalizedValue,
|
|
onAfterSubmit
|
|
);
|
|
}
|
|
};
|
|
</script>
|
|
<style>
|
|
.order-customer-search-modal {
|
|
max-width: calc(100vw - 2rem);
|
|
overflow: visible;
|
|
}
|
|
|
|
.order-customer-search-modal__content {
|
|
margin: 1rem 0 0;
|
|
overflow: visible;
|
|
padding: 0;
|
|
text-align: left;
|
|
}
|
|
</style>
|