Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CET-579/feat: Multiple invoice email support #62

Merged
Show file tree
Hide file tree
Changes from 2 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
10 changes: 10 additions & 0 deletions Api/Config/RepositoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ interface RepositoryInterface
public const XML_PATH_ENABLE_ADDRESS_SEARCH = 'payment/two_payment/enable_address_search';
public const XML_PATH_ENABLE_TAX_SUBTOTALS = 'payment/two_payment/enable_tax_subtotals';
public const XML_PATH_ENABLE_ORDER_INTENT = 'payment/two_payment/enable_order_intent';
public const XML_PATH_ENABLE_INVOICE_EMAILS = 'payment/two_payment/enable_invoice_emails';
public const XML_PATH_ENABLE_DEPARTMENT_NAME = 'payment/two_payment/enable_department';
public const XML_PATH_ENABLE_PROJECT_NAME = 'payment/two_payment/enable_project';
public const XML_PATH_ENABLE_ORDER_NOTE = 'payment/two_payment/enable_order_note';
Expand Down Expand Up @@ -122,6 +123,15 @@ public function isCompanySearchEnabled(?int $storeId = null): bool;
*/
public function isOrderIntentEnabled(?int $storeId = null): bool;

/**
* Check if invoice emails is enabled
*
* @param int|null $storeId
*
* @return bool
*/
public function isInvoiceEmailsEnabled(?int $storeId = null): bool;

/**
* Check if tax subtotals is enabled
*
Expand Down
8 changes: 8 additions & 0 deletions Model/Config/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,14 @@ public function isOrderIntentEnabled(?int $storeId = null): bool
return $this->isSetFlag(self::XML_PATH_ENABLE_ORDER_INTENT, $storeId);
}

/**
* @inheritDoc
*/
public function isInvoiceEmailsEnabled(?int $storeId = null): bool
{
return $this->isSetFlag(self::XML_PATH_ENABLE_INVOICE_EMAILS, $storeId);
}

/**
* @inheritDoc
*/
Expand Down
9 changes: 8 additions & 1 deletion Model/Two.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,19 @@ public function authorize(InfoInterface $payment, $amount)
$order = $payment->getOrder();
$this->urlCookie->delete();
$orderReference = (string)rand();

$additionalInformation = $payment->getAdditionalInformation();

$invoiceEmails = $additionalInformation['invoiceEmails'] ?? null;

$payload = $this->compositeOrder->execute(
$order,
$orderReference,
$payment->getAdditionalInformation()
$additionalInformation
);



// Create order
$response = $this->apiAdapter->execute('/v1/order', $payload);
$error = $this->getErrorFromResponse($response);
Expand Down
2 changes: 2 additions & 0 deletions Model/Ui/ConfigProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ public function getConfig(): array
'checkoutPageUrl' => $this->configRepository->getCheckoutPageUrl(),
'redirectUrlCookieCode' => UrlCookie::COOKIE_NAME,
'isOrderIntentEnabled' => $this->configRepository->isOrderIntentEnabled(),
'isInvoiceEmailsEnabled' => $this->configRepository->isInvoiceEmailsEnabled(),
'orderIntentConfig' => $orderIntentConfig,
'isCompanySearchEnabled' => $this->configRepository->isCompanySearchEnabled(),
'isAddressSearchEnabled' => $this->configRepository->isAddressSearchEnabled(),
Expand All @@ -115,6 +116,7 @@ public function getConfig(): array
$provider,
$tryAgainLater
),
'invalidEmailListMessage' => __('Please ensure your forward to email list only contains valid emails seperated by commas.'),
'paymentTermsMessage' => __(
'By checking this box, I confirm that I have read and agree to %1.',
sprintf('<a href="%s" target="_blank">%s</a>', $paymentTermsLink, $paymentTerms)
Expand Down
1 change: 1 addition & 0 deletions Observer/DataAssignObserver.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class DataAssignObserver extends AbstractDataAssignObserver
'department',
'orderNote',
'poNumber',
'invoiceEmails'
];

/**
Expand Down
90 changes: 55 additions & 35 deletions Service/Order/ComposeOrder.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,41 +27,61 @@ class ComposeOrder extends OrderService
* @throws LocalizedException
*/
public function execute(Order $order, string $orderReference, array $additionalData): array
{
$lineItems = $this->getLineItemsOrder($order);
{
// Fetch line items from the order
$lineItems = $this->getLineItemsOrder($order);


// Initialize invoice_details only if invoiceEmails is present
$invoiceDetails = [];
if (!empty($additionalData['invoiceEmails'])) {
$invoiceDetails['invoice_emails'] = explode(',', $additionalData['invoiceEmails']);
// Required placeholders to pass create order API Schema requirements
$invoiceDetails['payment_reference_message'] = "";
$invoiceDetails['payment_reference_ocr'] = "";
}

// Compose the final payload for the API call
$payload = [
'billing_address' => $this->getAddress($order, $additionalData, 'billing'),
'shipping_address' => $this->getAddress($order, $additionalData, 'shipping'),
'buyer' => $this->getBuyer($order, $additionalData),
'buyer_department' => $additionalData['department'] ?? '',
'buyer_project' => $additionalData['project'] ?? '',
'buyer_purchase_order_number' => $additionalData['poNumber'] ?? '',
'currency' => $order->getOrderCurrencyCode(),
'discount_amount' => $this->roundAmt($this->getDiscountAmountItem($order)),
'gross_amount' => $this->roundAmt($order->getGrandTotal()),
'net_amount' => $this->roundAmt($order->getGrandTotal() - $order->getTaxAmount()),
'tax_amount' => $this->roundAmt($order->getTaxAmount()),
'tax_subtotals' => $this->getTaxSubtotals($lineItems),
'invoice_type' => 'FUNDED_INVOICE',
'line_items' => $lineItems,
'merchant_order_id' => (string)($order->getIncrementId()),
'merchant_urls' => [
'merchant_confirmation_url' => $this->url->getUrl(
'two/payment/confirm',
['_two_order_reference' => base64_encode($orderReference)]
),
'merchant_cancel_order_url' => $this->url->getUrl(
'two/payment/cancel',
['_two_order_reference' => base64_encode($orderReference)]
),
'merchant_edit_order_url' => '',
'merchant_order_verification_failed_url' => $this->url->getUrl(
'two/payment/verificationfailed',
['_two_order_reference' => base64_encode($orderReference)]
),
],
'order_note' => $additionalData['orderNote'] ?? ''
];

// Add invoice_details only if invoiceEmails are present
if (!empty($invoiceDetails)) {
$payload['invoice_details'] = $invoiceDetails;
}


return [
'billing_address' => $this->getAddress($order, $additionalData, 'billing'),
'shipping_address' => $this->getAddress($order, $additionalData, 'shipping'),
'buyer' => $this->getBuyer($order, $additionalData),
'buyer_department' => $additionalData['department'] ?? '',
'buyer_project' => $additionalData['project'] ?? '',
'buyer_purchase_order_number' => $additionalData['poNumber'] ?? '',
'currency' => $order->getOrderCurrencyCode(),
'discount_amount' => $this->roundAmt($this->getDiscountAmountItem($order)),
'gross_amount' => $this->roundAmt($order->getGrandTotal()),
'net_amount' => $this->roundAmt($order->getGrandTotal() - $order->getTaxAmount()),
'tax_amount' => $this->roundAmt($order->getTaxAmount()),
'tax_subtotals' => $this->getTaxSubtotals($lineItems),
'invoice_type' => 'FUNDED_INVOICE',
'line_items' => $lineItems,
'merchant_order_id' => (string)($order->getIncrementId()),
'merchant_urls' => [
'merchant_confirmation_url' => $this->url->getUrl(
'two/payment/confirm',
['_two_order_reference' => base64_encode($orderReference)]
),
'merchant_cancel_order_url' => $this->url->getUrl(
'two/payment/cancel',
['_two_order_reference' => base64_encode($orderReference)]
),
'merchant_edit_order_url' => '',
'merchant_order_verification_failed_url' => $this->url->getUrl(
'two/payment/verificationfailed',
['_two_order_reference' => base64_encode($orderReference)]
),
],
'order_note' => $additionalData['orderNote'] ?? ''
];
return $payload;
}
}
10 changes: 10 additions & 0 deletions etc/adminhtml/system.xml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,16 @@
</depends>
<config_path>payment/two_payment/enable_order_intent</config_path>
</field>
<field id="enable_invoice_emails" translate="label" type="select" sortOrder="75" showInDefault="1"
showInWebsite="1" showInStore="1">
<label>Enable invoice emails</label>
<comment>Let your buyer input additional emails to forward the invoice to on order fulfilment.</comment>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<depends>
<field id="active">1</field>
</depends>
<config_path>payment/two_payment/enable_invoice_emails</config_path>
</field>
<field id="enable_tax_subtotals" translate="label" type="select" sortOrder="75" showInDefault="1"
showInWebsite="1" showInStore="1">
<label>Enable tax subtotals</label>
Expand Down
2 changes: 1 addition & 1 deletion etc/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<days_on_invoice>14</days_on_invoice>
<finalize_purchase>1</finalize_purchase>
<enable_order_intent>1</enable_order_intent>
<enable_invoice_emails>0</enable_invoice_emails>
<enable_tax_subtotals>1</enable_tax_subtotals>
<fulfill_trigger>shipment</fulfill_trigger>
<fulfill_order_status>complete</fulfill_order_status>
Expand All @@ -35,4 +36,3 @@
</payment>
</default>
</config>

2 changes: 2 additions & 0 deletions i18n/en_US.csv
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,5 @@ Version,Version
"Your request to %1 failed. Reason: %2","Your request to %1 failed. Reason: %2"
"Your sole trader account could not be verified.","Your sole trader account could not be verified."
"Zip/Postal Code is not valid.","Zip/Postal Code is not valid."
"Forward invoice to email list (optional)","Forward invoice to email list (optional)"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I missed this earlier, can we drop the (optional) and keep the wording similar to Woocom here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to match Woocom

"Please ensure your forward to email list only contains valid emails seperated by commas.", "Please ensure your forward to email list only contains valid emails seperated by commas."
2 changes: 2 additions & 0 deletions i18n/nb_NO.csv
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,5 @@ Version,Versjon
"Your request to %1 failed. Reason: %2","Din forespørsel til %1 mislyktes. Årsak: %2"
"Your sole trader account could not be verified.","Din eneforhandlerkonto kunne ikke bekreftes."
"Zip/Postal Code is not valid.","Postnummer er ikke gyldig."
"Forward invoice to email list (optional)","Videresend faktura til e-postliste (valgfritt)"
"Please ensure your forward to email list only contains valid emails seperated by commas.","Sørg for at listen over videresending til e-post kun inneholder gyldige e-poster atskilt med komma."
2 changes: 2 additions & 0 deletions i18n/nl_NL.csv
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,5 @@ Version,Versie
"Your request to %1 failed. Reason: %2","Uw verzoek aan %1 is mislukt. Reden: %2"
"Your sole trader account could not be verified.","Uw eenmanszaakaccount kon niet worden geverifieerd."
"Zip/Postal Code is not valid.","Postcode is niet geldig."
"Forward invoice to email list (optional)","Factuur doorsturen naar e-maillijst (optioneel)"
"Please ensure your forward to email list only contains valid emails seperated by commas.","Zorg ervoor dat uw doorstuur-naar-e-maillijst alleen geldige e-mails bevat, gescheiden door komma's."
2 changes: 2 additions & 0 deletions i18n/sv_SE.csv
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,5 @@ Version,Version
"Your request to %1 failed. Reason: %2","Din begäran till %1 misslyckades. Orsak: %2"
"Your sole trader account could not be verified.","Ditt enskild näringsidkarekonto kunde inte verifieras."
"Zip/Postal Code is not valid.","Postnummer är inte giltigt."
"Forward invoice to email list (optional)","Vidarebefordra faktura till e-postlista (valfritt)"
"Please ensure your forward to email list only contains valid emails seperated by commas.","Se till att din vidarebefordran till e-postlista endast innehåller giltiga e-postmeddelanden separerade med kommatecken."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please reword "Please ensure your forward to email list only contains valid emails seperated by commas" to "Please ensure that your invoice email address list only contains valid email addresses separated by commas"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ define([
orderIntentApprovedMessage: config.orderIntentApprovedMessage,
orderIntentDeclinedMessage: config.orderIntentDeclinedMessage,
generalErrorMessage: config.generalErrorMessage,
invalidEmailListMessage: config.invalidEmailListMessage,
soleTraderErrorMessage: config.soleTraderErrorMessage,
isOrderIntentEnabled: config.isOrderIntentEnabled,
isInvoiceEmailsEnabled: config.isInvoiceEmailsEnabled,
isDepartmentFieldEnabled: config.isDepartmentFieldEnabled,
isProjectFieldEnabled: config.isProjectFieldEnabled,
isOrderNoteFieldEnabled: config.isOrderNoteFieldEnabled,
Expand All @@ -67,6 +69,7 @@ define([
autofillToken: '',
companyName: ko.observable(''),
companyId: ko.observable(''),
invoiceEmails: ko.observable(''),
project: ko.observable(''),
department: ko.observable(''),
orderNote: ko.observable(''),
Expand All @@ -84,6 +87,28 @@ define([
this.configureFormValidation();
this.popupMessageListener();
},
showErrorMessage: function (message, duration) {
messageList.addErrorMessage({ message: message });

if (duration) {
setTimeout(function () {
messageList.messages.remove(function (item) {
return item.message === message;
});
}, duration);
}
},
validateEmails: function () {
const emails = this.invoiceEmails();
let emailArray = emails.split(',').map((email) => email.trim());

const isValid = emailArray.every((email) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email));
if (!isValid && emails) {
this.showErrorMessage(this.invalidEmailListMessage, 3);
return false;
}
return true;
},
logIsPaymentsAccepted: function (data, event) {
console.debug({
logger: 'logIsPaymentsAccepted',
Expand Down Expand Up @@ -217,6 +242,13 @@ define([
this.processTermsNotAcceptedErrorResponse();
return;
}

// Validate emails on the forward list
if (this.isInvoiceEmailsEnabled && !this.validateEmails()) {
this.showErrorMessage(this.invalidEmailListMessage);
return;
}

if (
this.validate() &&
additionalValidators.validate() &&
Expand Down Expand Up @@ -392,7 +424,8 @@ define([
project: this.project(),
department: this.department(),
orderNote: this.orderNote(),
poNumber: this.poNumber()
poNumber: this.poNumber(),
invoiceEmails: this.invoiceEmails()
}
};
},
Expand Down
13 changes: 13 additions & 0 deletions view/frontend/web/template/payment/two_payment.html
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,19 @@
/>
</div>
</div>
<div class="field field-text" data-bind="visible: isInvoiceEmailsEnabled">
<label for="invoice_emails" class="label">
<span data-bind="i18n: 'Forward invoice to email list (optional)'"></span>
</label>
<div class="control">
<input
type="text"
id="invoice_emails"
data-bind="value: invoiceEmails, event: { change: validateEmails }"
class="input-text"
/>
</div>
</div>
<div class="field field-text" data-bind="visible: isProjectFieldEnabled">
<label for="two_project" class="label">
<span> <!-- ko i18n: 'Project'--><!-- /ko --> </span>
Expand Down