feat(core): Add Merchant Tax ID in Merchant Profile (#8992)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
awasthi21
2025-09-01 16:08:45 +05:30
committed by GitHub
parent aae1994ea1
commit ff14b7cac8
7 changed files with 59 additions and 6 deletions

View File

@ -18941,6 +18941,11 @@
}
],
"nullable": true
},
"merchant_tax_registration_id": {
"type": "string",
"example": "123456789",
"nullable": true
}
},
"additionalProperties": false

View File

@ -14655,6 +14655,11 @@
}
],
"nullable": true
},
"merchant_tax_registration_id": {
"type": "string",
"example": "123456789",
"nullable": true
}
},
"additionalProperties": false

View File

@ -662,6 +662,9 @@ pub struct MerchantDetails {
/// The merchant's address details
pub address: Option<AddressDetails>,
#[schema(value_type = Option<String>, example = "123456789")]
pub merchant_tax_registration_id: Option<Secret<String>>,
}
#[derive(Clone, Debug, Deserialize, ToSchema, Serialize, PartialEq)]
#[serde(deny_unknown_fields)]

View File

@ -316,7 +316,7 @@ pub struct EnhancedData {
#[serde(skip_serializing_if = "Option::is_none")]
pub destination_country_code: Option<common_enums::CountryAlpha2>,
#[serde(skip_serializing_if = "Option::is_none")]
pub invoice_reference_number: Option<String>,
pub detail_tax: Option<DetailTax>,
#[serde(skip_serializing_if = "Option::is_none")]
pub line_item_data: Option<Vec<LineItemData>>,
}
@ -324,10 +324,11 @@ pub struct EnhancedData {
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DetailTax {
#[serde(skip_serializing_if = "Option::is_none")]
pub tax_included_in_total: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tax_amount: Option<MinorUnit>,
pub tax_rate: Option<String>,
pub tax_type_identifier: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub card_acceptor_tax_id: Option<Secret<String>>,
}
@ -356,7 +357,6 @@ pub struct LineItemData {
pub commodity_code: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub unit_cost: Option<MinorUnit>,
// pub detail_tax: Option<DetailTax>,
}
#[derive(Debug, Serialize, Deserialize)]
@ -938,7 +938,7 @@ where
{
let l2_l3_data = item.get_optional_l2_l3_data();
if let Some(l2_l3_data) = l2_l3_data {
let line_item_data = l2_l3_data.order_details.map(|order_details| {
let line_item_data = l2_l3_data.order_details.as_ref().map(|order_details| {
order_details
.iter()
.enumerate()
@ -969,6 +969,25 @@ where
let customer_reference =
get_vantiv_customer_reference(&l2_l3_data.merchant_order_reference_id);
let detail_tax: Option<DetailTax> = if l2_l3_data.merchant_tax_registration_id.is_some()
&& l2_l3_data.order_details.is_some()
{
Some(DetailTax {
tax_included_in_total: match tax_exempt {
Some(false) => Some(true),
Some(true) | None => Some(false),
},
card_acceptor_tax_id: l2_l3_data.merchant_tax_registration_id.clone(),
tax_amount: l2_l3_data.order_details.as_ref().map(|orders| {
orders
.iter()
.filter_map(|order| order.total_tax_amount)
.fold(MinorUnit::zero(), |acc, tax| acc + tax)
}),
})
} else {
None
};
let enhanced_data = EnhancedData {
customer_reference,
sales_tax: l2_l3_data.order_tax_amount,
@ -979,7 +998,7 @@ where
ship_from_postal_code: l2_l3_data.shipping_origin_zip,
destination_postal_code: l2_l3_data.shipping_destination_zip,
destination_country_code: l2_l3_data.shipping_country,
invoice_reference_number: l2_l3_data.merchant_order_reference_id,
detail_tax,
line_item_data,
};
Ok(Some(enhanced_data))

View File

@ -223,6 +223,22 @@ impl MerchantAccount {
&self.organization_id
}
/// Get the merchant_details from MerchantAccount
pub fn get_merchant_details(&self) -> &OptionalEncryptableValue {
&self.merchant_details
}
/// Extract merchant_tax_registration_id from merchant_details
pub fn get_merchant_tax_registration_id(&self) -> Option<Secret<String>> {
self.merchant_details.as_ref().and_then(|details| {
details
.get_inner()
.peek()
.get("merchant_tax_registration_id")
.and_then(|id| id.as_str().map(|s| Secret::new(s.to_string())))
})
}
/// Check whether the merchant account is a platform account
pub fn is_platform_account(&self) -> bool {
matches!(

View File

@ -132,6 +132,7 @@ pub struct L2L3Data {
pub shipping_country: Option<common_enums::CountryAlpha2>,
pub shipping_destination_zip: Option<Secret<String>>,
pub billing_address_city: Option<String>,
pub merchant_tax_registration_id: Option<Secret<String>>,
}
// Different patterns of authentication.

View File

@ -1548,6 +1548,9 @@ where
let l2_l3_data = state.conf.l2_l3_data_config.enabled.then(|| {
let shipping_address = unified_address.get_shipping();
let billing_address = unified_address.get_payment_billing();
let merchant_tax_registration_id = merchant_context
.get_merchant_account()
.get_merchant_tax_registration_id();
types::L2L3Data {
order_date: payment_data.payment_intent.order_date,
@ -1590,6 +1593,7 @@ where
.as_ref()
.and_then(|addr| addr.address.as_ref())
.and_then(|details| details.city.clone()),
merchant_tax_registration_id,
}
});
crate::logger::debug!("unified address details {:?}", unified_address);