init
This commit is contained in:
@@ -1,154 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { ResponseMapper } from '../../common/response/response-mapper'
|
||||
import { PrismaService } from '../../prisma/prisma.service'
|
||||
|
||||
@Injectable()
|
||||
export class PosService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
|
||||
async getInfo(posId: number) {
|
||||
const info = await this.prisma.posAccount.findUniqueOrThrow({
|
||||
where: { id: posId },
|
||||
include: {
|
||||
inventoryBankAccount: {
|
||||
include: {
|
||||
bankAccount: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
accountNumber: true,
|
||||
branch: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
bank: { select: { id: true, name: true } },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
inventory: {
|
||||
select: { id: true, name: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const { inventoryBankAccount, ...rest } = info
|
||||
|
||||
return ResponseMapper.single({
|
||||
...rest,
|
||||
bankAccount: inventoryBankAccount?.bankAccount,
|
||||
inventory: inventoryBankAccount?.inventory,
|
||||
})
|
||||
}
|
||||
|
||||
async getStock(
|
||||
posId: number,
|
||||
options: {
|
||||
isAvailable?: boolean
|
||||
page?: number
|
||||
pageSize?: number
|
||||
q?: string
|
||||
productIds?: number[]
|
||||
} = {},
|
||||
) {
|
||||
const { isAvailable, page = 1, pageSize = 50, q, productIds } = options
|
||||
const pos = await this.prisma.posAccount.findUniqueOrThrow({
|
||||
where: { id: posId },
|
||||
select: { inventoryId: true },
|
||||
})
|
||||
const inventoryId = pos.inventoryId
|
||||
|
||||
let sql = `
|
||||
SELECT sb.productId, sb.quantity - COALESCE(SUM(sr.quantity), 0) as availableQuantity, p.id, p.name, p.sku, p.description, p.salePrice, p.categoryId
|
||||
FROM Stock_Balance sb
|
||||
LEFT JOIN Stock_Reservations sr ON sb.productId = sr.productId AND sb.inventoryId = sr.inventoryId
|
||||
LEFT JOIN Products p ON sb.productId = p.id
|
||||
WHERE sb.inventoryId = ?
|
||||
`
|
||||
const params: any[] = [inventoryId]
|
||||
|
||||
if (productIds && productIds.length > 0) {
|
||||
sql += ` AND sb.productId IN (${productIds.map(() => '?').join(',')})`
|
||||
params.push(...productIds)
|
||||
}
|
||||
|
||||
if (q) {
|
||||
sql += ` AND (p.name LIKE ? OR p.sku LIKE ?)`
|
||||
params.push(`%${q}%`, `%${q}%`)
|
||||
}
|
||||
|
||||
sql += ` GROUP BY sb.productId`
|
||||
|
||||
if (isAvailable !== undefined) {
|
||||
sql += isAvailable
|
||||
? ` HAVING availableQuantity > 0`
|
||||
: ` HAVING availableQuantity <= 0`
|
||||
}
|
||||
|
||||
sql += ` ORDER BY sb.quantity DESC`
|
||||
|
||||
const items = await this.prisma.$queryRawUnsafe(sql, ...params)
|
||||
|
||||
const mapped = (items as any[]).map(item => ({
|
||||
id: item.productId,
|
||||
quantity: Number(item.availableQuantity),
|
||||
product: {
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
sku: item.sku,
|
||||
description: item.description,
|
||||
salePrice: item.salePrice,
|
||||
categoryId: item.categoryId,
|
||||
},
|
||||
}))
|
||||
|
||||
const count = mapped.length
|
||||
const paginated = mapped.slice((page - 1) * pageSize, page * pageSize)
|
||||
|
||||
return ResponseMapper.paginate(paginated, count, page, pageSize)
|
||||
}
|
||||
|
||||
async getProductCategories(posId: number) {
|
||||
const pos = await this.prisma.posAccount.findUniqueOrThrow({
|
||||
where: { id: posId },
|
||||
select: { inventoryId: true },
|
||||
})
|
||||
const inventoryId = pos.inventoryId
|
||||
|
||||
const balances = await this.prisma.stockBalance.findMany({
|
||||
where: { inventoryId },
|
||||
select: {
|
||||
product: { select: { id: true, category: { select: { id: true, name: true } } } },
|
||||
quantity: true,
|
||||
},
|
||||
})
|
||||
|
||||
const map = new Map<
|
||||
number,
|
||||
{ id: number; name: string; totalQuantity: number; productCount: number }
|
||||
>()
|
||||
|
||||
for (const b of balances) {
|
||||
const product = b.product
|
||||
const cat = product?.category
|
||||
if (!cat) continue // skip products without category
|
||||
const existing = map.get(cat.id)
|
||||
if (existing) {
|
||||
existing.totalQuantity += Number(b.quantity)
|
||||
existing.productCount += 1
|
||||
} else {
|
||||
map.set(cat.id, {
|
||||
id: cat.id,
|
||||
name: cat.name,
|
||||
totalQuantity: Number(b.quantity),
|
||||
productCount: 1,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const categories = Array.from(map.values())
|
||||
return ResponseMapper.list(categories)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user