Updates tax after address / coupon change

main
Ashelyn Dawn 5 years ago
parent d09ae8464e
commit d0b5b67025

@ -7,5 +7,6 @@ module.exports = {
cart: require('./models/cart'),
order: require('./models/order'),
address: require('./models/address'),
coupon: require('./models/coupon')
coupon: require('./models/coupon'),
config: require('./models/config')
}

@ -0,0 +1,11 @@
module.exports = [{
mapId: 'configMap',
idProperty: 'uuid',
properties: [
'date_updated',
'default_tax_percent'
],
associations: [
{name: 'modified_by', mapId: 'userMap', columnPrefix: 'user_'},
]
}]

@ -1,4 +1,5 @@
module.exports = [
...require('./config'),
...require('./user'),
...require('./item'),
...require('./order')

@ -21,8 +21,7 @@ module.exports = [{
'urlslug',
'price_cents',
'published',
'number_in_stock',
'tax_rate'
'number_in_stock'
],
collections: [
{name: 'images', mapId: 'imageMap', columnPrefix: 'image_'}

@ -0,0 +1,18 @@
const pg = require('../pg')
const joinjs = require('join-js').default;
const debug = require('debug')('sos:db:config')
const mappings = require('../mappings')
const config = module.exports = {}
config.getLatestConfig = async () => {
const {rows} = await pg.query('select * from sos.v_config')
return joinjs.mapOne(rows, mappings, 'configMap', 'config_')
}
config.getTaxRate = async () => {
const current = await config.getLatestConfig()
console.log(parseFloat(current.default_tax_percent))
return parseFloat(current.default_tax_percent)
}

@ -4,6 +4,8 @@ const debug = require('debug')('sos:db:order')
const mappings = require('../mappings')
const dbUtil = require('../util')
const config = require('./config')
const {DateTime} = require('luxon')
const easypost = new (require('@easypost/api'))(process.env.EASYPOST_API_KEY);
@ -45,6 +47,16 @@ order.findAllForSession = async function(session_uuid) {
return joinjs.map(rows, mappings, 'orderMap', 'order_');
}
order.findForTransaction = transaction_uuid =>
dbUtil.executeFunction({
name: 'find_order_for_transaction',
params: [
transaction_uuid
],
returnType: 'order',
single: true
})
order.addAddress = async function (transaction, address){
// Get parcel size
const parcel = {
@ -75,24 +87,59 @@ order.addAddress = async function (transaction, address){
if(!price)
throw new Error("Unable to estimate price");
// TODO: Update with real tax rate
const tax = epShipment.to_address.state === 'UT'
? 200
: null
// Add up tax for all the items
const tax = epShipment.to_address.state !== 'UT'
? null
: transaction.cart.items
// For each item type, create an array of length n (number of items of that type in cart)
// where each index is initialized to the item tax amount
.map(({item, count}) => new Array(count).fill(item.tax_rate * item.price_cents / 100))
// Flatten to just be all tax amounts
.flat()
// Sum all the numbers
.reduce((a,c) => (a+c))
// Update database
const query = {
text: 'select * from sos.add_address_to_order($1, $2, $3, $4)',
values: [transaction.uuid, address.uuid, price, tax]
text: 'select * from sos.add_address_to_order($1, $2, $3)',
values: [transaction.uuid, address.uuid, price]
}
debug(query)
const {rows} = await pg.query(query)
await pg.query(query)
return joinjs.map(rows, mappings, 'orderMap', 'order_')[0];
// Update tax
return await order.updateTax(transaction.uuid)
}
order.updateTax = async function(transaction_uuid){
const _order = await order.findForTransaction(transaction_uuid)
if(!_order.address)
throw new Error("Order has no address");
if(_order.address.state !== 'UT'){
debug("Skipping tax for state: " + _order.address.state);
return
}
const {item_total_price, coupon_effective_discount} = _order.transactions.find(t => t.uuid === transaction_uuid)
const itemPriceWithDiscount = item_total_price - (coupon_effective_discount || 0)
const taxRate = await config.getTaxRate()
const computedTax = Math.round(itemPriceWithDiscount * taxRate / 100)
return await dbUtil.executeFunction({
name: 'add_tax_to_transaction',
params: [
transaction_uuid,
computedTax
],
returnType: 'order',
single: true
})
}
order.addCoupon = function(transaction, coupon) {
order.addCoupon = async function(transaction, coupon) {
// Check coupon validity
const couponExpireTime = DateTime.fromJSDate(coupon.valid_until)
if(couponExpireTime.diffNow().as('seconds') < 0)
@ -133,7 +180,7 @@ order.addCoupon = function(transaction, coupon) {
// Sum the item costs for total discount
.reduce((a,c) => (a+c))
return dbUtil.executeFunction({
await dbUtil.executeFunction({
name: 'add_coupon_to_transaction',
params: [
transaction.uuid,
@ -143,6 +190,9 @@ order.addCoupon = function(transaction, coupon) {
returnType: 'order',
single: true
})
// Update tax
return await order.updateTax(transaction.uuid)
}
order.addPayment = async function(transaction, paymentIntent){

@ -46,8 +46,7 @@ create table sos."item" (
item_description text not null,
item_urlslug citext unique not null,
item_price_cents integer not null,
item_published boolean not null default true,
item_tax_percent_override numeric(8,6) null
item_published boolean not null default true
);
create table sos."cart_item" (
@ -264,5 +263,10 @@ create table sos."item_stockchange_admin" (
);
create table sos."config" (
config_uuid uuid primary key default uuid_generate_v4(),
config_date_updated timestamptz not null default now(),
config_updated_by uuid references sos."user" (user_uuid),
config_default_tax_percent numeric(8,6) not null default 7.250
);
insert into sos."config" default values;

@ -6,7 +6,6 @@ create or replace view sos.v_item as
"item".item_urlslug,
"item".item_price_cents,
"item".item_published,
coalesce("item".item_tax_percent_override, "config".config_default_tax_percent) as item_tax_rate,
"image".image_uuid,
"image".image_featured,
"image".image_mime_type,
@ -14,7 +13,6 @@ create or replace view sos.v_item as
"user".user_email as uploader_email,
coalesce(num_added - num_removed, 0) as item_number_in_stock
from sos."item"
left join sos."config" on true
left join sos."image" on item.item_uuid = image.image_item_uuid
left join sos."user" on image.image_uploader_uuid = "user".user_uuid
left join
@ -125,3 +123,8 @@ create or replace view sos.v_order as
left join sos.v_transaction_paid on "transaction".transaction_uuid = v_transaction_paid.transaction_uuid
left join sos.v_payment on "transaction".transaction_uuid = payment_transaction_uuid
left join sos.v_cart on cart_uuid = transaction_cart_uuid;
create or replace view sos.v_config as
select * from sos."config"
left join sos."user" on config_updated_by = user_uuid
where config_date_updated = (select max(config_date_updated) from sos."config")

@ -555,7 +555,7 @@ begin
return query select * from sos."address" where address_uuid = _address_uuid;
end; $function$;
create or replace function sos.add_address_to_order(_transaction_uuid uuid, _address_uuid uuid, _shipping_price integer, _tax_price integer)
create or replace function sos.add_address_to_order(_transaction_uuid uuid, _address_uuid uuid, _shipping_price integer)
returns setof sos.v_order
language plpgsql
as $function$
@ -589,13 +589,9 @@ begin
where order_uuid = _order_uuid;
-- Update transaction with price
update sos."transaction" set (
transaction_shipping_price,
transaction_tax_price
) = (
_shipping_price,
_tax_price
) where transaction_uuid = _transaction_uuid;
update sos."transaction" set
transaction_shipping_price = _shipping_price
where transaction_uuid = _transaction_uuid;
return query select * from sos.v_order where order_uuid = _order_uuid;
end; $function$;
@ -671,6 +667,16 @@ begin
return query select * from sos.v_order where order_uuid = _order_uuid;
end; $function$;
create or replace function sos.find_order_for_transaction(_transaction_uuid uuid)
returns setof sos.v_order
language plpgsql
as $function$
begin
return query select v_order.* from sos."transaction"
left join sos.v_order on "transaction".transaction_order_uuid = v_order.order_uuid
where "transaction".transaction_uuid = _transaction_uuid;
end; $function$;
create or replace function sos.add_stripe_payment_to_transaction(_transaction_uuid uuid, _payment_value_cents integer, _stripe_intent_id text, _stripe_reciept_email citext)
returns setof sos.v_order
language plpgsql
@ -806,3 +812,16 @@ begin
return query select * from sos.v_item where item_uuid = any(_item_uuids);
end; $function$;
create or replace function sos.add_tax_to_transaction(_transaction_uuid uuid, _tax_price integer)
returns setof sos.v_order
language plpgsql
as $function$
begin
-- Update transaction
update sos."transaction" set
transaction_tax_price = _tax_price
where transaction_uuid = _transaction_uuid;
return query select * from sos.find_order_for_transaction(_transaction_uuid);
end; $function$;

Loading…
Cancel
Save