import fs from 'fs/promises';
import path from 'path';
import { select } from '@evershop/postgres-query-builder';
import { CONSTANTS } from '../../../../lib/helpers.js';
import { countries } from '../../../../lib/locale/countries.js';
import { provinces } from '../../../../lib/locale/provinces.js';
import { translate } from '../../../../lib/locale/translate/translate.js';
import { debug, error } from '../../../../lib/log/logger.js';
import {
buildEmailBodyFromTemplate,
sendEmail
} from '../../../../lib/mail/emailHelper.js';
import { pool } from '../../../../lib/postgres/connection.js';
import { getBaseUrl } from '../../../../lib/util/getBaseUrl.js';
import { getConfig } from '../../../../lib/util/getConfig.js';
import { getValue } from '../../../../lib/util/registry.js';
import { EventData } from '../../../../types/event.js';
const TEMPLATE = `
{{#if storeInfo.logo}}
{{/if}}
Your order has been confirmed. Thanks for shopping with us.
{{#if storeInfo.logo}}
{{/if}}
Thanks for shopping with us.
|
Order Number
#{{order.order_number}}
|
Order Date
{{date order.created_at}}
|
|
|
{{#if shippingAddress}}
|
Shipping to: {{shippingAddress.full_name}}
{{shippingAddress.address_1}}, {{shippingAddress.city}},
{{shippingAddress.province_name}}
{{shippingAddress.postcode}}
|
{{/if}}
{{#each order.items}}
|
{{this.product_name}}
{{this.qty}} | {{currency this.final_price}}
|
{{/each}}
|
|
Subtotal:
|
{{currency order.sub_total}}
|
{{#if order.discount_amount}}
|
Discount:
|
-{{currency order.discount_amount}}
|
{{/if}}
|
Shipping:
|
{{currency order.shipping_fee_incl_tax}}
|
|
Tax:
|
{{currency order.tax_amount}}
|
|
Total:
|
{{currency order.grand_total}}
|
|
Please contact us if you have any questions.
{{storeInfo.address.street}},
{{storeInfo.address.city}},
{{storeInfo.address.state}}
{{storeInfo.address.zip}},
{{storeInfo.address.country}}
|
|
`;
export default async function sendOrderConfirmationEmail(
data: EventData<'order_placed'>
) {
try {
const config = getConfig('system.notification_emails.order_confirmation', {
enabled: true
});
if (config?.enabled === false) {
return;
}
// Build the email data
const orderId = data.order_id;
const order = await select()
.from('order')
.where('order_id', '=', orderId)
.load(pool);
if (!order) {
return;
}
const items = await select()
.from('order_item')
.where('order_item_order_id', '=', order.order_id)
.execute(pool);
// Loop through each item to add the base Url before the thumbnail path
order.items = items.map((item) => {
if (item.thumbnail) {
const baseUrl = getBaseUrl();
item.thumbnail = `${baseUrl}${item.thumbnail}`;
}
return item;
});
const shippingAddress = await select()
.from('order_address')
.where('order_address_id', '=', order.shipping_address_id)
.load(pool);
if (!data.no_shipping_required) {
shippingAddress.country_name =
countries.find((c) => c.code === shippingAddress.country)?.name || '';
shippingAddress.province_name =
provinces.find((p) => p.code === shippingAddress.province)?.name || '';
}
const billingAddress = await select()
.from('order_address')
.where('order_address_id', '=', order.billing_address_id)
.load(pool);
billingAddress.country_name =
countries.find((c) => c.code === billingAddress.country)?.name || '';
billingAddress.province_name =
provinces.find((p) => p.code === billingAddress.province)?.name || '';
let template;
if (config?.templatePath) {
const filePath = path.join(CONSTANTS.ROOTPATH, config.templatePath);
try {
await fs.access(filePath);
template = await fs.readFile(filePath, 'utf8');
} catch (error) {
debug(
`Order confirmation email template file not found at path: ${filePath}. Using default template.`
);
template = TEMPLATE;
}
} else {
template = TEMPLATE;
}
const dynamicData = await getValue('orderConfirmationEmailData', {
order,
shippingAddress,
billingAddress
});
const subject = translate('Your order has been confirmed!');
if (data.customer_email) {
const args = await getValue(
'orderConfirmationEmailArguments',
{
to: data.customer_email,
subject,
template,
data: dynamicData
},
{ order }
);
await sendEmail('order_confirmation', args);
}
} catch (e) {
error(e);
}
}