Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 18 additions & 13 deletions src/app/api/quickbooks/invoice/invoice.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,8 @@ export class InvoiceService extends BaseService {
const priceUpdatePayload = {
copilotUnitPrice: itemAmount,
}
const conditions = eq(QBProductSync.id, mappingId) as WhereClause
const conditions = eq(QBProductSync.id, mappingId)

await productService.updateQBProduct(priceUpdatePayload, conditions)
console.info('Copilot unit price updated in mapping table')
return itemAmount
Expand All @@ -181,6 +182,19 @@ export class InvoiceService extends BaseService {
incomeAccRef: string,
): Promise<InvoiceItemRefAndDescriptionType> {
const productService = new ProductService(this.user)

// get product info from assembly
const productInfo = await this.copilot.getProduct(productId)
if (!productInfo) {
throw new APIError(
httpStatus.NOT_FOUND,
'Product not found. Id: ' + productId,
)
}
const productDescription = productInfo.description
? convert(productInfo.description)
: ''

const mapping = await productService.ensureProductExistsAndSyncToken(
productId,
priceId,
Expand Down Expand Up @@ -211,7 +225,7 @@ export class InvoiceService extends BaseService {
return {
ref: { value: mapping.qbItemId },
amount: parseFloat(itemAmount) / 100,
productDescription: mapping.description || '',
productDescription,
// classRef is optional. A classRef to the mapped QB item is checked every time for each item when creating an invoice.
classRef: intuitItem.ClassRef,
}
Expand All @@ -232,19 +246,10 @@ export class InvoiceService extends BaseService {
}

// 2. create a new product in QB company
const productInfo = await this.copilot.getProduct(productId)
const priceInfo = await this.copilot.getPrice(priceId)
if (!productInfo) {
throw new APIError(
httpStatus.NOT_FOUND,
'Product not found. Id: ' + productId,
)
}
if (!priceInfo) {
throw new APIError(httpStatus.NOT_FOUND, 'Price not found. Id:' + priceId)
}

const productDescription = convert(productInfo.description)
const incomeAccRefVal = incomeAccRef

// total products with the same product id
Expand Down Expand Up @@ -464,7 +469,7 @@ export class InvoiceService extends BaseService {
): Promise<QBInvoiceLineItemSchemaType | undefined> {
const invoice = invoiceResource.data
// check invoice fee is paid by client
const clientWithFee = invoice?.paymentMethodPreferences.find(
const clientWithFee = invoice?.paymentMethodPreferences?.find(
(preference) => preference.feePaidByClient === true,
)
if (clientWithFee) {
Expand All @@ -489,7 +494,7 @@ export class InvoiceService extends BaseService {

const feeAmount =
payments.data.reduce((acc, payment) => {
if (payment.feeAmount.paidByClient > 0) {
if (!!payment.feeAmount?.paidByClient) {
return acc + payment.feeAmount.paidByClient
}
return acc
Expand Down
14 changes: 8 additions & 6 deletions src/type/dto/webhook.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@ export const InvoiceCreatedResponseSchema = z.object({
taxPercentage: z.number().default(0),
sentDate: z.string().datetime().nullish(),
dueDate: z.string().datetime().nullish(),
paymentMethodPreferences: z.array(
z.object({
type: z.string(),
feePaidByClient: z.boolean(),
}),
),
paymentMethodPreferences: z
.array(
z.object({
type: z.string(),
feePaidByClient: z.boolean(),
}),
)
.optional(),
}),
})

Expand Down
Loading