Compare commits
2 commits
c774e9f44c
...
61825309d1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61825309d1 | ||
|
|
250bbca226 |
2 changed files with 215 additions and 0 deletions
|
|
@ -30,6 +30,7 @@ import { deleteFile, deleteFolder, fileLocation, getFile, listFile, setFile } fr
|
||||||
import { isUsedError, notFoundError, relationError } from "../utils/error";
|
import { isUsedError, notFoundError, relationError } from "../utils/error";
|
||||||
import { queryOrNot, whereDateQuery } from "../utils/relation";
|
import { queryOrNot, whereDateQuery } from "../utils/relation";
|
||||||
import spreadsheet from "../utils/spreadsheet";
|
import spreadsheet from "../utils/spreadsheet";
|
||||||
|
import flowAccount from "../services/flowaccount";
|
||||||
|
|
||||||
const MANAGE_ROLES = [
|
const MANAGE_ROLES = [
|
||||||
"system",
|
"system",
|
||||||
|
|
@ -299,6 +300,9 @@ export class ProductController extends Controller {
|
||||||
},
|
},
|
||||||
update: { value: { increment: 1 } },
|
update: { value: { increment: 1 } },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const listId = await flowAccount.createProducts(body);
|
||||||
|
|
||||||
return await prisma.product.create({
|
return await prisma.product.create({
|
||||||
include: {
|
include: {
|
||||||
createdBy: true,
|
createdBy: true,
|
||||||
|
|
@ -306,6 +310,8 @@ export class ProductController extends Controller {
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
...body,
|
...body,
|
||||||
|
flowAccountProductIdAgentPrice: `${listId.data.productIdAgentPrice}`,
|
||||||
|
flowAccountProductIdSellPrice: `${listId.data.productIdSellPrice}`,
|
||||||
document: body.document
|
document: body.document
|
||||||
? {
|
? {
|
||||||
createMany: { data: body.document.map((v) => ({ name: v })) },
|
createMany: { data: body.document.map((v) => ({ name: v })) },
|
||||||
|
|
@ -379,6 +385,19 @@ export class ProductController extends Controller {
|
||||||
await permissionCheck(req.user, productGroup.registeredBranch);
|
await permissionCheck(req.user, productGroup.registeredBranch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
product.flowAccountProductIdSellPrice !== null &&
|
||||||
|
product.flowAccountProductIdAgentPrice !== null
|
||||||
|
) {
|
||||||
|
await flowAccount.editProducts(
|
||||||
|
product.flowAccountProductIdSellPrice,
|
||||||
|
product.flowAccountProductIdAgentPrice,
|
||||||
|
body,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw notFoundError("FlowAccountProductId");
|
||||||
|
}
|
||||||
|
|
||||||
const record = await prisma.product.update({
|
const record = await prisma.product.update({
|
||||||
include: {
|
include: {
|
||||||
productGroup: true,
|
productGroup: true,
|
||||||
|
|
@ -441,6 +460,18 @@ export class ProductController extends Controller {
|
||||||
|
|
||||||
if (record.status !== Status.CREATED) throw isUsedError("Product");
|
if (record.status !== Status.CREATED) throw isUsedError("Product");
|
||||||
|
|
||||||
|
if (
|
||||||
|
record.flowAccountProductIdSellPrice !== null &&
|
||||||
|
record.flowAccountProductIdAgentPrice !== null
|
||||||
|
) {
|
||||||
|
await Promise.all([
|
||||||
|
flowAccount.deleteProduct(record.flowAccountProductIdSellPrice),
|
||||||
|
flowAccount.deleteProduct(record.flowAccountProductIdAgentPrice),
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
throw notFoundError("FlowAccountProductId");
|
||||||
|
}
|
||||||
|
|
||||||
await deleteFolder(fileLocation.product.img(productId));
|
await deleteFolder(fileLocation.product.img(productId));
|
||||||
|
|
||||||
return await prisma.product.delete({
|
return await prisma.product.delete({
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import config from "../config.json";
|
||||||
import { CustomerType, PayCondition } from "@prisma/client";
|
import { CustomerType, PayCondition } from "@prisma/client";
|
||||||
import { convertTemplate } from "../utils/string-template";
|
import { convertTemplate } from "../utils/string-template";
|
||||||
import { htmlToText } from "html-to-text";
|
import { htmlToText } from "html-to-text";
|
||||||
|
import { JsonObject } from "@prisma/client/runtime/library";
|
||||||
|
|
||||||
if (!process.env.FLOW_ACCOUNT_URL) throw new Error("Require FLOW_ACCOUNT_URL");
|
if (!process.env.FLOW_ACCOUNT_URL) throw new Error("Require FLOW_ACCOUNT_URL");
|
||||||
if (!process.env.FLOW_ACCOUNT_CLIENT_ID) throw new Error("Require FLOW_ACCOUNT_CLIENT_ID");
|
if (!process.env.FLOW_ACCOUNT_CLIENT_ID) throw new Error("Require FLOW_ACCOUNT_CLIENT_ID");
|
||||||
|
|
@ -388,6 +389,189 @@ const flowAccount = {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// flowAccount GET Product list
|
||||||
|
async getProducts() {
|
||||||
|
const { token } = await flowAccountAPI.auth();
|
||||||
|
|
||||||
|
const res = await fetch(api + "/products", {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
["Content-Type"]: `application/json`,
|
||||||
|
["Authorization"]: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
ok: res.ok,
|
||||||
|
status: res.status,
|
||||||
|
body: await res.json(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
// flowAccount GET Product by id
|
||||||
|
async getProductsById(recordId: string) {
|
||||||
|
const { token } = await flowAccountAPI.auth();
|
||||||
|
|
||||||
|
const res = await fetch(api + `/products/${recordId}`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
["Content-Type"]: `application/json`,
|
||||||
|
["Authorization"]: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
return {
|
||||||
|
ok: res.ok,
|
||||||
|
status: res.status,
|
||||||
|
list: data.data.list,
|
||||||
|
total: data.data.total,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
// flowAccount POST create Product
|
||||||
|
async createProducts(body: JsonObject) {
|
||||||
|
const { token } = await flowAccountAPI.auth();
|
||||||
|
|
||||||
|
const commonBody = {
|
||||||
|
productStructureType: null,
|
||||||
|
type: "3",
|
||||||
|
name: body.name,
|
||||||
|
sellDescription: body.detail,
|
||||||
|
sellVatType: 3,
|
||||||
|
unitName: "Unit",
|
||||||
|
categoryName: "Car",
|
||||||
|
}; // helper function สำหรับสร้าง product
|
||||||
|
|
||||||
|
const createProduct = async (price: any, vatIncluded: boolean) => {
|
||||||
|
try {
|
||||||
|
const res = await fetch(api + "/products", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
...commonBody,
|
||||||
|
sellPrice: price,
|
||||||
|
sellVatType: vatIncluded ? 1 : 3,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error(`Request failed with status ${res.status}`);
|
||||||
|
} // ป้องกัน response ที่ไม่ใช่ JSON หรือว่าง
|
||||||
|
|
||||||
|
let json: any = null;
|
||||||
|
try {
|
||||||
|
json = await res.json();
|
||||||
|
} catch {
|
||||||
|
throw new Error("Response is not valid JSON");
|
||||||
|
}
|
||||||
|
|
||||||
|
return json?.data?.list?.[0]?.id ?? null;
|
||||||
|
} catch (err) {
|
||||||
|
console.error("createProduct error:", err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const [sellId, agentId] = await Promise.all([
|
||||||
|
createProduct(body.price, /true/.test(`${body.vatIncluded}`)),
|
||||||
|
createProduct(body.agentPrice, /true/.test(`${body.agentPriceVatIncluded}`)),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
ok: !!(agentId && sellId),
|
||||||
|
status: agentId && sellId ? 200 : 500,
|
||||||
|
data: {
|
||||||
|
productIdAgentPrice: agentId,
|
||||||
|
productIdSellPrice: sellId,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
// flowAccount PUT edit Product
|
||||||
|
async editProducts(sellPriceId: String, agentPriceId: String, body: JsonObject) {
|
||||||
|
console.log("body: ", body);
|
||||||
|
const { token } = await flowAccountAPI.auth();
|
||||||
|
|
||||||
|
const commonBody = {
|
||||||
|
productStructureType: null,
|
||||||
|
type: "3",
|
||||||
|
name: body.name,
|
||||||
|
sellDescription: body.detail,
|
||||||
|
sellVatType: 3,
|
||||||
|
unitName: "Unit",
|
||||||
|
categoryName: "Car",
|
||||||
|
}; // helper function สำหรับสร้าง product
|
||||||
|
|
||||||
|
const editProduct = async (id: String, price: any, vatIncluded: boolean) => {
|
||||||
|
try {
|
||||||
|
const res = await fetch(api + `/products/${id}`, {
|
||||||
|
method: "PUT",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
...commonBody,
|
||||||
|
sellPrice: price,
|
||||||
|
sellVatType: vatIncluded ? 1 : 3,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error(`Request failed with status ${res.status}`);
|
||||||
|
} // ป้องกัน response ที่ไม่ใช่ JSON หรือว่าง
|
||||||
|
|
||||||
|
let json: any = null;
|
||||||
|
try {
|
||||||
|
json = await res.json();
|
||||||
|
} catch {
|
||||||
|
throw new Error("Response is not valid JSON");
|
||||||
|
}
|
||||||
|
|
||||||
|
return json?.data?.list?.[0]?.id ?? null;
|
||||||
|
} catch (err) {
|
||||||
|
console.error("createProduct error:", err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const [agentId, sellId] = await Promise.all([
|
||||||
|
editProduct(sellPriceId, body.price, /true/.test(`${body.vatIncluded}`)),
|
||||||
|
editProduct(agentPriceId, body.agentPrice, /true/.test(`${body.agentPriceVatIncluded}`)),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
ok: !!(agentId && sellId),
|
||||||
|
status: agentId && sellId ? 200 : 500,
|
||||||
|
data: {
|
||||||
|
productIdAgentPrice: agentId,
|
||||||
|
productIdSellPrice: sellId,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
// flowAccount DELETE Product
|
||||||
|
async deleteProduct(recordId: string) {
|
||||||
|
const { token } = await flowAccountAPI.auth();
|
||||||
|
|
||||||
|
const res = await fetch(api + `/products/${recordId}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
["Authorization"]: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
ok: res.ok,
|
||||||
|
status: res.status,
|
||||||
|
};
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default flowAccount;
|
export default flowAccount;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue