How to divide amount unequally in Plutus Smart Contracts - smartcontracts

I need to make a smart contract using Plutus to divide an amount to 2 wallet unequally so I can define custom fees for each transaction. I am using this documentation. What I need is that I would like to split the amount to two unequal amounts and send each to a separate wallet. Assume a user wants to send 7$ to wallet B from his wallet A. The additional fee which I have defined before for each transaction is 2$. using code block below, How can I divide 9$ to 7$ and 2$, then send them to wallets B and C (C is my wallet).
validateSplit :: SplitData -> () -> ScriptContext -> Bool
validateSplit SplitData{recipient1, recipient2, amount} _ ScriptContext{scriptContextTxInfo} =
let half = Ada.divide amount 2 in
Ada.fromValue (valuePaidTo scriptContextTxInfo recipient1) >= half &&
Ada.fromValue (valuePaidTo scriptContextTxInfo recipient2) >= (amount - half)

Well if you know your fee beforehand, why not include it in the parameter list recipient1, recipient2, amount, fee. So then you can subtract it accordingly. Or if it is always 2 Ada and will always be 2 Ada, then simply hardcode it in the contract. How else should the contract know how much is the fee which goes to your wallet (C) and how much should go to the other wallet (B).

Related

Integrating Netsuite back-end into Snowflake - how to find the exact currency exchange rates?

I'm using imported back-end tables from Netsuite in Snowflake.
I'm trying to determine exact exchange rates for foreign currency transactions to get the identical totals Netsuite has on the front-end. So I tried using Netsuite's "Currency" and "CurrencyRate" tables, but the amounts I am getting are incorrect.
The exchange rates from the table don't seem the same as those used on the front-end. Every amount I get is off by a little, which adds up when there are many transactions.
Is there another table I should keep an eye out for, or do they do something completely different to keep track of all the effective exchange rates on the back-end? Here's the query I have so far:
select
transline.transaction,
transline.id as line_item_id,
transline.creditforeignamount,
transline.rate,
transline.rateamount,
tran.currency as transaction_currency,
tran.recordtype,
tran.trandate::date as trandate,
tran.TRANID as netsuite_document_number,
tran.custbody_cust_primcurrfxrate,
transline.custcol_invoice_prim_curr_fx_rate, tran.exchangerate as tran_exchange_rate,
cr.exchangerate as officialexchangerate,
round((case
when cr.exchangerate not like 'null' then (cr.exchangerate * transline.creditforeignamount)
else creditforeignamount
end), 2) as amount
from transactionline transline
inner join transaction tran
on tran.id = transline.transaction
left join currencyrate cr
on (tran.currency = cr.transactioncurrency
and tran.custbody_cust_primcurrfxrate = cr.basecurrency
and tran.closedate = cr.effectivedate)
The issue may be that each transaction has an exchangerate field.
This is because each transaction may have been done at a custom rate and Netsuite should calculate an exchange rate gain/loss for you based on the difference between the transaction exchange rate and the official posted exchange rate (i.e. the currencyrate tables).
Common sources of differences:
bank transfers between currencies - you use the bank's forex rate
negotiated exchange rates for trading partners
user error where a transaction all takes place in one currency and the data entry person puts 1.0 as the rate. (e.g. Your company uses USD. You have a Canadian supplier who invoices in CAD and whom you pay from a CAD bank account. A naive user might put 1 as the exchange rate because all the transactions are in CAD but all the transactions actually should have had the USD - CAD rate for the date of the transaciton)

Database and code approach for auto generated invoices

Let's say I manage a Domain name site where I sell domain names and their hosting.
Each of my clients will have a cost:
Domain name: example.com
Cost: 100.00 dollars
Duration: 1 year
What I want to do in my program, is to auto generate an invoice when their domain name is about to expire.
I already have the following approach:
Recurring invoice table:
Recurring_Invoices
InvoiceID[ID]
domain_name[VARCHAR]
Price[Double]
Last_Invoice_Date[DATETIME]
Is_Recurring[BYTE]
Next_Invoice_Date[DATETIME]
My approach on my code level is the following:
Every time my program gets launched, I will check if there are invoices to be generated for that month. In pseudo code I will do:
void getRecurringInvoices()
{
//Select the invoices WHERE Is_Recurring = 1
}
foreach (Invoice i in RecurringInvoices)
{
// Get the month of Next_Invoice_Date
if(Month of Next_Invoice_Date == DateTime.Now.Month)
{
//this is an invoice that needs to be generated + Next Invoice Date needs
to be prolonged with 1 year
}
I wanted to ask if this is approach is OK. My only concern with this one is that if my program doesn't get run for 1 month, recurring invoices of that month won't be generated.
That's why I'm still having my doubts off this approach.
What could I do to optimize this process?

Correct way to calculate prices including tax in foreign currencies

I'm trying to upgrade an application so that I can sell to multiple countries. I store all of my prices in the database in GBP excluding tax up to 4dp and I need to calculate the prices in the country's currency including tax.
Do I multiply the price by the exchange rate against the price excluding tax (option 1) or do I calculate the amount including tax and then multiple by the exchange rate (option 2)? I have also added an option 3 after looking at how OpenCart calculates it which is similar to option 2 but only ever rounds when displaying it. Here are the formula's for all 3 options:
Option 1:
Round((Price * Exchange Rate) / 100 * (100 + Tax Rate))
Option 2:
Round(Round(Price / 100 * (100 + Tax Rate)) * Exchange Rate)
Option 3:
Round((Price / 100 * (100 + Tax Rate)) * Exchange Rate)
For example say I have a product with a price of 89.99. If I wanted to display that in a currency with an exchange rate of 1.5 and a tax rate of 20%. Would I say:
Option 1:
Round((89.99 * 1.5) / 100 * (100 + 20)) = 161.98
Option 2:
Round(Round(89.99 / 100 * (100 + 20)) * 1.5) = 161.99
Option 3:
Round((89.99 / 100 * (100 + 20)) * 1.5) = 161.98
I've found that OpenCart always multiplies the unrounded figures by the exchange rate at the end. For example their formula for calculating the line total is:
Round((Price / 100 * (100 + Tax Rate)) * Quantity * Exchange Rate)
So if I was to order 3 of my product's it would give:
Round((89.99 / 100 * (100 + 20)) * 3 * 1.5) = 485.95
The problem I find doing it OpenCart's way is the user will see an item price (including tax) of 161.98 and a line total of 485.95. However if I say 161.98 * 3 I get 485.94, so it doesn't sum up correctly.
It's important I get this right as you can see I'll end up with penny issues. I'd appreciate it if someone could let me know which way is correct or suggest an alternative if none are right. Thanks
Since all variables are rounded except Exchange Rate, which I would expect to usually look something like this 1.3462, we can write a test like this:
// I'm guessing you need it in PHP
$price = 89.99;
$quantity = 1;
$tax = 20;
$tax = $tax/100.0 + 1;
// $tax = 1.2
$exchangeRate = 1.5;
$totalPrice = $price*$quantity*$tax; // Test #1
$totalPriceRounded = round($price*$quantity*$tax,2); // Test #2
echo $totalPrice.'<br/>'.$totalPriceRounded;
Which would have this output:
107.988 // Test #1 <--- This is amount that needs to be paid to you and Great Britain
107.99 // Test #2 <--- rounded
Now, it's obvious there is a difference in amount, so which to choose? Since you are charging an item from Great Britain, you expect to get paid the full amount you are asking for, in GBP, so lets rely on that factor. In the end, if I understood correctly, the tax the customer has to pay is tax to Great Britain.
Lets check the final prices in foreign currency:
$totalPrice = round($totalPrice * $exchangeRate,2);
$totalPriceRounded = round($totalPriceRounded * $exchangeRate,2);
echo $totalPrice.'<br/>'.$totalPriceRounded;
Which would have this output:
// Amount in foreign currency
161.98 // Test #1
161.99 // Test #2
With all that said, lets check which one of these would return you a value closest to 107.988 GBP when calculated back to GBP from foreign currency.
// To calculate the totalPrice back to price*tax*quantity in GBP
$totalPrice /= $exchangeRate;
$totalPriceRounded /= $exchangeRate;
echo $totalPrice.'<br/>'.$totalPriceRounded;
Output of which is:
// totalPrice in GBP currency
107.98666666667 // Test #1
107.99333333333 // Test #2
And when we divide by tax:
$totalPrice /= $tax;
$totalPriceRounded /= $tax;
echo $totalPrice.'<br/>'.$totalPriceRounded;
Output is:
// the amount you get in GBP currency
89.988888888889 // End result of Test #1
89.994444444444 // End result of Test #2
So as you can see, in this case, by using the bare amount of round($price*$quantity*$tax*$exchangeRate, 2) you are getting less, but by using round(round($price*$quantity*$tax,2)*$exchangeRate, 2) you get a little more which again, rounded both give the same value. In some other scenario the difference will likely be different from what we got here and might be the other way around.
CONCLUSION
If you have a fixed number of products each with fixed prices then you will be either loosing money (an insignificant amount) or earning more than you should (also an insignificant amount) over time. The outcome depends on the popularity and price of each product (i.e. will the round function round up or down), and on the way of calculation you chose. You could, depending on product popularity, manually adjust the prices of each product to minimize the loss/gain over time.
If you have products with random prices like lets say you are renting web servers and the price is $0.01/second. Then the expectation value for your loss/gain is close to zero. And the more purchases are made the closer to zero it gets. So you are not loosing anything here regardless of the approach. One time you win some one time you loose some.
In my opinion I would standardize it to round everything:
$price = 4.47;
$quantity = 1.2 // lets say liters
// Even round the price before applying tax
$totalPrice = round($price * $quantity, 2);
because if you are forced to show all the different stages of calculation then you will have to round every step.
But the most precise would be to use this as the least information is lost:
// Round once at end
$totalPrice = round($price*$quantity*$tax*$exchangeRate, 2);
In the end it all depends on how you set up your product prices or how your pricing works to be able to choose which method to go with. I'd say it doesn't really matter, I think every company simply chooses what suits them best.
Legally, some countries/cities/etc. have laws on how to calculate this, you should be looking at Great Britain laws to check on the valid procedure for your problem.
I can't tell you what the correct option is or even if there is one correct option. But from experience I can say, if there are multiple options to do one thing, make it configurable in your software. In this case you can easily use the strategy pattern and make the strategy for calculating prices configurable. Customers can choose how they want it calculated.
The correct solution depends on your business. When you sell items in different countries, you most likely have branches in those countries - and you need a net price in those country's currency. This results in the net price per item "translated" to the foreign currency, and this net price is then multiplied with the amount and multiplied with the tax factor/percentage).
The EU MOSS (which is charged when you offer services in other countries, or e.g. software as download) is somehow different. You can sell products with GBP pricing, but have to consider your consumer's local tax factor. See e.g. https://ec.europa.eu/taxation_customs/sites/taxation/files/resources/documents/taxation/vat/how_vat_works/telecom/one-stop-shop-guidelines_en.pdf
For MOSS, I didn't check in detail, but I expect that you then have a different formula, using your local GBP net price per item, multiply with amount, multiply with consumer's tax percentage. This tax amount, still in GBP, should then be multiplied with currency exchange rate, I'd expect.

SQL :Write a function to return value based on business rule

I am trying to figure out the way in writing a function to do the following in the best possible way.
I need to write a function that will return me the exchange name. It will be referred in my view query below
select Exchange,ISIN,Investment_Codename,PROPORTION_NEWCASH,PROPORTION_MIDCAP,PROPORTION_SMALLCAP,PROPORTION_LARGECAP from FundPrice
Following are the rules of my function
1. If fund type=Listed Equity, AIM, Investment Company, Investment Trust, VCT or ETP and Update code=FinexDD/MM/YYYY
should rturn LSE
For anything else apart from the updatecode mentioned above with Fund Type = Listed Equity, need to take left two letters of the ISIN Code to indicate the country e.g. Microsoft=US5949181045, Michelin=FR0000121261 and infer the exchange name based on that
(CASE WHEN UpdatedCode <> 'LSE' THEN LEFT(Investment_Codename, 2)) AS [Country Code]
I think I understood your question. The above checks to see if UpdatedCode is NOT LSE, if it isn't it will take the Investment Code name, and present the first 2 characters. E.g. GB.

SQL 2008 Cursor needed?

I'm building a function to return the net value of a sales invoice once any purchase invoices marked against it have been taken off - part of these costs are contractor costs of which we also want to calculate either NI or a set increase to the contractor pay to reflect "true" value.
So on one sales invoice, we may have several contractors where we have purchase invoices against it, some may be at NI calculated at 13.8%, others may be at a standard "uplift" of 10% and others may be at 0% added.
The bit that I'm trying to figure out is if I need to make the whole function as a cursor as there are going to be different figures for a variable for each purchase invoice
e.g.
(SELECT SUM(th.hoursworked * (th.payrate * (1 + (#NIAMOUNT / 100))) )
but the #NIAMOUNT will have to change for each purchase invoice.
Is the best way of doing this via a cursor, or is there a better way of doing this?
Sorry if this is a bit verbose!
You should avoid cursors wherever possible - cursors operate 'serially' which will limit SQL's performance.
If the calculation is simple, one way to do this would be do do the NI lookup inline, e.g.
(SELECT SUM(th.hoursworked * (th.payrate * (1 +
((CASE somejoinedtable.UpliftType
WHEN 1 THEN 10
WHEN 2 THEN 13.8
WHEN 3 THEN 0
END
/ 100))))
If this becomes too messy to do inline, you could abstract a user defined function
CREATE FUNCTION dbo.fnGetNIAmount(int #someLookupParam)
...
And then do like so
(SELECT SUM(th.hoursworked * (th.payrate * (1 +
((dbo.fnGetNIAmount(somejoinedtable.UpliftType )
/ 100))))
You almost certainly don't need a cursor
Join your hours worked to the contract they are based on, and take the NI value from the contract.