u
This commit is contained in:
@@ -2,6 +2,8 @@ import { Router } from 'express';
|
||||
import { posAuthMiddleware } from './middleware/posAuth.js';
|
||||
import { handleClient } from './routes/client.js';
|
||||
import { handleInit } from './routes/init.js';
|
||||
import { handleCategory } from './routes/category.js';
|
||||
import { handleProduct } from './routes/product.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
@@ -11,5 +13,9 @@ router.get('/client', handleClient);
|
||||
// POS sync initialization counts
|
||||
router.get('/init', posAuthMiddleware, handleInit);
|
||||
|
||||
// POS master data synchronization
|
||||
router.get('/category', posAuthMiddleware, handleCategory);
|
||||
router.get('/product', posAuthMiddleware, handleProduct);
|
||||
|
||||
export default router;
|
||||
|
||||
|
||||
67
src/v1/routes/category.js
Normal file
67
src/v1/routes/category.js
Normal file
@@ -0,0 +1,67 @@
|
||||
import { getCategoryList } from '../../db/posterminal.js';
|
||||
|
||||
function formatServerTimestamp() {
|
||||
const d = new Date();
|
||||
const pad = (n) => String(n).padStart(2, '0');
|
||||
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /v1/category:
|
||||
* get:
|
||||
* summary: JTL-POS category synchronization
|
||||
* description: Returns category hierarchy modified after lastChangedCategory cursor for the authenticated POS register.
|
||||
* tags:
|
||||
* - POS Sync
|
||||
* security:
|
||||
* - BearerAuth: []
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: lastChangedCategory
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Unix timestamp cursor of last category sync
|
||||
* - in: query
|
||||
* name: limit
|
||||
* schema:
|
||||
* type: integer
|
||||
* default: 50
|
||||
* description: Maximum number of categories to return
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Array of category objects for JTL-POS
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: array
|
||||
* items:
|
||||
* type: object
|
||||
* 401:
|
||||
* description: Unauthorized
|
||||
*/
|
||||
export async function handleCategory(req, res, next) {
|
||||
try {
|
||||
const posterminal = req.posterminal;
|
||||
const cursor = Number(req.query.lastChangedCategory) || 0;
|
||||
const limit = Number(req.query.limit) || 20;
|
||||
|
||||
const categories = await getCategoryList({
|
||||
posterminalId: posterminal.id,
|
||||
cursor,
|
||||
limit,
|
||||
});
|
||||
|
||||
const timestamp = formatServerTimestamp();
|
||||
|
||||
res.json(
|
||||
categories.map((category) => ({
|
||||
...category,
|
||||
updated_at: timestamp,
|
||||
created_at: timestamp,
|
||||
}))
|
||||
);
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
}
|
||||
104
src/v1/routes/product.js
Normal file
104
src/v1/routes/product.js
Normal file
@@ -0,0 +1,104 @@
|
||||
import { getProductList } from '../../db/posterminal.js';
|
||||
|
||||
const STATIC_DEFAULTS = {
|
||||
sort: '0',
|
||||
p_price: '0.00',
|
||||
discountable: '0',
|
||||
deposit: '0',
|
||||
discount: '',
|
||||
d_price: '0.0',
|
||||
tax_rate2: '',
|
||||
use_in_out_tax: '0',
|
||||
barcode: null,
|
||||
use_stock: '0',
|
||||
q_div: '0',
|
||||
quantity: '0',
|
||||
unit: null,
|
||||
single_bookable: '0',
|
||||
annotation: '',
|
||||
status: '0',
|
||||
tags: '',
|
||||
is_parent: '0',
|
||||
parent: '0',
|
||||
variants: '',
|
||||
print_kitchen_receipt: '0',
|
||||
deposit_name: '',
|
||||
updated_at: '0001-01-01 00:00:00',
|
||||
isCompositeProduct: '0',
|
||||
attributes: [],
|
||||
configurationGroups: '',
|
||||
options: null,
|
||||
hasBestBeforeDate: '0',
|
||||
hasLotNumber: '0',
|
||||
hasSerialNumber: '0',
|
||||
PLU: '',
|
||||
short_description: '',
|
||||
minStock: '0',
|
||||
container: [],
|
||||
reservedQuantity: '0.00',
|
||||
deliveryDetails: [],
|
||||
isbn: '',
|
||||
manufacturerName: null,
|
||||
han: null,
|
||||
productType: '0',
|
||||
voucherData: null,
|
||||
inputPrice: '0',
|
||||
inputQuantity: '0',
|
||||
};
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /v1/product:
|
||||
* get:
|
||||
* summary: JTL-POS product catalog synchronization
|
||||
* description: Returns product catalog with prices, stock, variants, and image hashes modified after lastChangedProduct cursor.
|
||||
* tags:
|
||||
* - POS Sync
|
||||
* security:
|
||||
* - BearerAuth: []
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: lastChangedProduct
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Unix timestamp cursor of last product sync
|
||||
* - in: query
|
||||
* name: limit
|
||||
* schema:
|
||||
* type: integer
|
||||
* default: 50
|
||||
* description: Maximum number of products to return
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Array of product objects for JTL-POS
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: array
|
||||
* items:
|
||||
* type: object
|
||||
* 401:
|
||||
* description: Unauthorized
|
||||
*/
|
||||
export async function handleProduct(req, res, next) {
|
||||
try {
|
||||
const posterminal = req.posterminal;
|
||||
const cursor = Number(req.query.lastChangedProduct) || 0;
|
||||
const limit = Number(req.query.limit) || 20;
|
||||
|
||||
const products = await getProductList({
|
||||
posterminalId: posterminal.id,
|
||||
cursor,
|
||||
limit,
|
||||
});
|
||||
|
||||
res.json(
|
||||
products.map((product) => ({
|
||||
...STATIC_DEFAULTS,
|
||||
...product,
|
||||
}))
|
||||
);
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user