cache
parent
f9bf88c55f
commit
b61112d1e3
|
@ -0,0 +1,25 @@
|
|||
package app
|
||||
|
||||
import "sync"
|
||||
|
||||
var accountCache = accountCacheType{
|
||||
obj: map[string]*Account{},
|
||||
}
|
||||
|
||||
type accountCacheType struct {
|
||||
sync.RWMutex
|
||||
obj map[string]*Account
|
||||
}
|
||||
|
||||
func (m *accountCacheType) get(recordID string) (*Account, bool) {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
r, ok := m.obj[recordID]
|
||||
return r, ok
|
||||
}
|
||||
|
||||
func (m *accountCacheType) put(recordID string, itm *Account) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
m.obj[recordID] = itm
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.tnxs.net/taxnexus/lib/api/crm/crm_client/accounts"
|
||||
)
|
||||
|
||||
func GetAccount(key string, principal *User) Account {
|
||||
if key == "" {
|
||||
return Account{}
|
||||
}
|
||||
a, ok := accountCache.get(key)
|
||||
if ok {
|
||||
return *a
|
||||
}
|
||||
acct, err := GetAccountByID(key, principal)
|
||||
if err != nil {
|
||||
return Account{}
|
||||
}
|
||||
return acct
|
||||
}
|
||||
|
||||
func GetAccountByID(recordID string, principal *User) (Account, error) {
|
||||
sugar.Debug("app.GetAccountByID: 📥")
|
||||
if recordID == "" {
|
||||
return Account{}, fmt.Errorf("app.getAccountByID: 💣 ⛔ key is blank")
|
||||
}
|
||||
obj, ok := accountCache.get(recordID)
|
||||
if ok {
|
||||
sugar.Debug("app.getAccountByID: 👍 🎯 📤")
|
||||
return *obj, nil
|
||||
}
|
||||
crmParams := accounts.NewGetAccountsParamsWithTimeout(getTimeout)
|
||||
crmParams.AccountID = &recordID
|
||||
response, err := crmClient.Accounts.GetAccounts(crmParams, principal.Auth)
|
||||
if err != nil {
|
||||
return Account{}, err
|
||||
}
|
||||
var newObj *Account
|
||||
for _, itm := range response.Payload.Data { // single iteration execution
|
||||
newObj = UnMarshalAccount(itm)
|
||||
}
|
||||
accountCache.put(recordID, newObj)
|
||||
sugar.Debug("app.getAccountByID: 👍 🆕 📤")
|
||||
return *newObj, nil
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"code.tnxs.net/taxnexus/lib/api/geo/geo_models"
|
||||
)
|
||||
|
||||
var countyCache = countyCacheType{
|
||||
obj: map[string]*geo_models.County{},
|
||||
}
|
||||
|
||||
type countyCacheType struct {
|
||||
sync.RWMutex
|
||||
obj map[string]*geo_models.County
|
||||
}
|
||||
|
||||
func (m *countyCacheType) get(key string) (*geo_models.County, bool) {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
r, ok := m.obj[key]
|
||||
return r, ok
|
||||
}
|
||||
|
||||
func (m *countyCacheType) put(key string, obj *geo_models.County) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
m.obj[key] = obj
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.tnxs.net/taxnexus/lib/api/geo/geo_client/county"
|
||||
"code.tnxs.net/taxnexus/lib/api/geo/geo_models"
|
||||
)
|
||||
|
||||
func GetCountyNameByGeocode(key string, principal *User) string {
|
||||
if key == "" {
|
||||
return ""
|
||||
}
|
||||
if len(key) == countyGeocodeLength {
|
||||
c, ok := countyCache.get(key)
|
||||
if ok {
|
||||
return c.Name
|
||||
}
|
||||
obj, err := GetCountyByGeocode(key, principal)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return obj.Name
|
||||
}
|
||||
obj, ok := placeCache.get(key)
|
||||
if ok {
|
||||
return obj.SalesTaxRate.County
|
||||
}
|
||||
place, err := getPlaceByGeocode(key, principal)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return place.SalesTaxRate.County
|
||||
}
|
||||
func GetCountyByGeocode(recordID string, principal *User) (geo_models.County, error) {
|
||||
sugar.Debug("plex.getCountyByGeocode: 📥")
|
||||
if recordID == "" {
|
||||
return geo_models.County{}, fmt.Errorf("plex.getCountyByID: 💣 ⛔ key is blank")
|
||||
}
|
||||
obj, ok := countyCache.get(recordID)
|
||||
if ok {
|
||||
sugar.Debug("plex.getCountyByGeocode: 👍 🎯 📤")
|
||||
return *obj, nil
|
||||
}
|
||||
geoParams := county.NewGetCountiesParamsWithTimeout(getTimeout)
|
||||
geoParams.Geocode = &recordID
|
||||
response, err := geoClient.County.GetCounties(geoParams, principal.Auth)
|
||||
if err != nil {
|
||||
return geo_models.County{}, err
|
||||
}
|
||||
var newObj *geo_models.County
|
||||
for _, itm := range response.Payload.Data { // single iteration execution
|
||||
newObj = itm
|
||||
}
|
||||
countyCache.put(recordID, newObj)
|
||||
sugar.Debug("plex.getCountyByGeocode: 👍 🆕 📤")
|
||||
return *newObj, nil
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"code.tnxs.net/taxnexus/lib/api/geo/geo_models"
|
||||
)
|
||||
|
||||
var placeCache = placeCacheType{
|
||||
obj: map[string]*geo_models.Place{},
|
||||
}
|
||||
|
||||
type placeCacheType struct {
|
||||
sync.RWMutex
|
||||
obj map[string]*geo_models.Place
|
||||
}
|
||||
|
||||
func (m *placeCacheType) get(key string) (*geo_models.Place, bool) {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
r, ok := m.obj[key]
|
||||
return r, ok
|
||||
}
|
||||
|
||||
func (m *placeCacheType) put(key string, obj *geo_models.Place) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
m.obj[key] = obj
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.tnxs.net/taxnexus/lib/api/geo/geo_client/place"
|
||||
"code.tnxs.net/taxnexus/lib/api/geo/geo_models"
|
||||
)
|
||||
|
||||
func getPlaceNameByGeocode(key string, principal *User) string {
|
||||
if key == "" || len(key) == 7 {
|
||||
return ""
|
||||
}
|
||||
p, ok := placeCache.get(key)
|
||||
if ok {
|
||||
return p.Name
|
||||
}
|
||||
thePlace, err := getPlaceByGeocode(key, principal)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return thePlace.Name
|
||||
}
|
||||
func getPlaceHasDistrictTaxesByGeocode(key string, principal *User) bool {
|
||||
if key == "" || len(key) == 7 {
|
||||
return false
|
||||
}
|
||||
p, ok := placeCache.get(key)
|
||||
if ok {
|
||||
return p.HasDistrictTaxes
|
||||
}
|
||||
thePlace, err := getPlaceByGeocode(key, principal)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return thePlace.HasDistrictTaxes
|
||||
}
|
||||
|
||||
func getPlaceByGeocode(recordID string, principal *User) (geo_models.Place, error) {
|
||||
sugar.Debug("plex.getPlaceByGeocode: 📥")
|
||||
if recordID == "" {
|
||||
return geo_models.Place{}, fmt.Errorf("plex.getPlaceByID: 💣 ⛔ key is blank")
|
||||
}
|
||||
obj, ok := placeCache.get(recordID)
|
||||
if ok {
|
||||
sugar.Debug("plex.getPlaceByGeocode: 👍 🎯 📤")
|
||||
return *obj, nil
|
||||
}
|
||||
geoParams := place.NewGetPlacesParamsWithTimeout(getTimeout)
|
||||
geoParams.Geocode = &recordID
|
||||
response, err := geoClient.Place.GetPlaces(geoParams, principal.Auth)
|
||||
if err != nil {
|
||||
return geo_models.Place{}, err
|
||||
}
|
||||
var newObj *geo_models.Place
|
||||
for _, itm := range response.Payload.Data { // single iteration execution
|
||||
newObj = itm
|
||||
}
|
||||
placeCache.put(recordID, newObj)
|
||||
sugar.Debug("plex.getPlaceByGeocode: 👍 🆕 📤")
|
||||
return *newObj, nil
|
||||
}
|
|
@ -6,6 +6,8 @@ import (
|
|||
"time"
|
||||
|
||||
"code.tnxs.net/taxnexus/lib/api/auth0/auth0_client"
|
||||
"code.tnxs.net/taxnexus/lib/api/crm/crm_client"
|
||||
"code.tnxs.net/taxnexus/lib/api/geo/geo_client"
|
||||
"code.tnxs.net/taxnexus/lib/app/logger"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/spf13/viper"
|
||||
|
@ -17,6 +19,8 @@ var sugar *zap.SugaredLogger
|
|||
var config = Configuration{}
|
||||
var appViper = viper.New()
|
||||
var auth0Client = auth0_client.Default
|
||||
var geoClient = geo_client.Default
|
||||
var crmClient = crm_client.Default
|
||||
var configured = false
|
||||
var apiUsers map[string]User
|
||||
|
||||
|
@ -27,6 +31,8 @@ const dateFormat = "2006-01-02"
|
|||
const dateTimeFormat = "2006-01-02T15:04:05-0800"
|
||||
const dateTimeFormatAlt = "2006-01-02 15:04:05"
|
||||
const dateFormatAlt = "1/2/2006"
|
||||
const countyGeocodeLength = 7
|
||||
const cityGeocodeLength = 12
|
||||
|
||||
// InitConfig exports the config initialization func
|
||||
func InitConfig(systemName string, initalLogLevel zapcore.Level) {
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package app
|
||||
|
||||
import "sync"
|
||||
|
||||
var taxTypeCache = taxTypeCacheType{
|
||||
obj: map[string]*TaxType{},
|
||||
}
|
||||
|
||||
type taxTypeCacheType struct {
|
||||
sync.RWMutex
|
||||
obj map[string]*TaxType
|
||||
}
|
||||
|
||||
func (m *taxTypeCacheType) get(recordID string) (*TaxType, bool) {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
r, ok := m.obj[recordID]
|
||||
return r, ok
|
||||
}
|
||||
|
||||
func (m *taxTypeCacheType) put(recordID string, itm *TaxType) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
m.obj[recordID] = itm
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.tnxs.net/taxnexus/lib/api/geo/geo_client/tax_type"
|
||||
)
|
||||
|
||||
var exciseCategories = map[string]string{
|
||||
"cannabis-excise": "cannabis-excise",
|
||||
"telecom-excise": "telecom-excise",
|
||||
}
|
||||
|
||||
var cannabisCategories = map[string]string{
|
||||
"cannabis-ag": "cannabis-ag",
|
||||
"cannabis-trade": "cannabis-trade",
|
||||
}
|
||||
|
||||
var merchCategories = map[string]string{
|
||||
"cannabis-retail": "cannabis-retail",
|
||||
"sales-district": "sales-district",
|
||||
"sales-state": "sales-state",
|
||||
}
|
||||
|
||||
var telecomCategories = map[string]string{
|
||||
"broadband": "broadband",
|
||||
"voip-interstate": "voip-interstate",
|
||||
"voip-international": "voip-international",
|
||||
"voip-intrastate": "voip-intrastate",
|
||||
"voip": "voip",
|
||||
"wireless": "wireless",
|
||||
}
|
||||
|
||||
func GetTaxType(recordID string, principal *User) *TaxType {
|
||||
obj, ok := taxTypeCache.get(recordID)
|
||||
if ok {
|
||||
return obj
|
||||
}
|
||||
obj, err := GetTaxTypeByID(recordID, principal)
|
||||
if err != nil {
|
||||
return &TaxType{}
|
||||
}
|
||||
return obj
|
||||
}
|
||||
func GetTaxTypeByID(recordID string, principal *User) (*TaxType, error) {
|
||||
sugar.Debugf("render.GetTaxTypesByID: 📥")
|
||||
if recordID == "" {
|
||||
return nil, fmt.Errorf("render.getTaxTypeByID: 💣 ⛔ key is blank")
|
||||
}
|
||||
obj, ok := taxTypeCache.get(recordID)
|
||||
if ok {
|
||||
sugar.Debugf("render.getTaxTypeByID: 👍 🎯 📤")
|
||||
return obj, nil
|
||||
}
|
||||
geoParams := tax_type.NewGetTaxTypesParamsWithTimeout(getTimeout)
|
||||
geoParams.TaxTypeID = &recordID
|
||||
response, err := geoClient.TaxType.GetTaxTypes(geoParams, principal.Auth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var newObj *TaxType
|
||||
for _, itm := range response.Payload.Data { // single iteration execution
|
||||
newObj = UnMarshalTaxType(itm)
|
||||
}
|
||||
taxTypeCache.put(recordID, newObj)
|
||||
sugar.Debugf("render.getTaxTypeByID: 👍 🆕 📤")
|
||||
return newObj, nil
|
||||
}
|
||||
|
||||
func GetCannabisTaxTypes(taxTypes []*TaxType) []*TaxType {
|
||||
objList := []*TaxType{}
|
||||
for _, tt := range taxTypes {
|
||||
if tt != nil {
|
||||
if inMap(cannabisCategories, tt.Category) && isActive(tt) {
|
||||
sugar.Debugf("render.getCannabisTaxTypes: ➡ ✅ cannabis %s", tt.Name)
|
||||
objList = append(objList, tt)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(objList) == 0 {
|
||||
return nil
|
||||
}
|
||||
return objList
|
||||
}
|
||||
|
||||
func GetExciseTaxTypes(taxTypes []*TaxType) []*TaxType {
|
||||
objList := []*TaxType{}
|
||||
for _, tt := range taxTypes {
|
||||
if tt != nil {
|
||||
if inMap(exciseCategories, tt.Category) && isActive(tt) {
|
||||
sugar.Debugf("render.getExciseTaxTypes: ➡ ✅ excise %s", tt.Name)
|
||||
objList = append(objList, tt)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(objList) == 0 {
|
||||
return nil
|
||||
}
|
||||
return objList
|
||||
}
|
||||
|
||||
func GetBusinessTaxTypes(taxTypes []*TaxType) []*TaxType {
|
||||
objList := []*TaxType{}
|
||||
for _, tt := range taxTypes {
|
||||
if tt != nil {
|
||||
if tt.Category == "business" && isActive(tt) {
|
||||
sugar.Debugf("render.getBusinessTaxTypes: ➡ ✅ business %s", tt.Name)
|
||||
objList = append(objList, tt)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(objList) == 0 {
|
||||
return nil
|
||||
}
|
||||
return objList
|
||||
}
|
||||
|
||||
func GetMerchTaxTypes(taxTypes []*TaxType) []*TaxType {
|
||||
objList := []*TaxType{}
|
||||
for _, tt := range taxTypes {
|
||||
if tt != nil {
|
||||
if inMap(merchCategories, tt.Category) && isActive(tt) {
|
||||
sugar.Debugf("render.getMerchTaxTypes: ➡ ✅ merch %s", tt.Name)
|
||||
objList = append(objList, tt)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(objList) == 0 {
|
||||
return nil
|
||||
}
|
||||
return objList
|
||||
}
|
||||
func GetTelecomTaxTypes(taxTypes []*TaxType) []*TaxType {
|
||||
objList := []*TaxType{}
|
||||
for _, tt := range taxTypes {
|
||||
if tt != nil {
|
||||
if inMap(telecomCategories, tt.Category) && isActive(tt) {
|
||||
sugar.Debugf("render.getTelecomTaxTypes: ➡ ✅ telecom %s", tt.Name)
|
||||
objList = append(objList, tt)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(objList) == 0 {
|
||||
return nil
|
||||
}
|
||||
return objList
|
||||
}
|
||||
|
||||
func inMap(values map[string]string, str string) bool {
|
||||
_, ok := values[str]
|
||||
return ok
|
||||
}
|
||||
func isActive(tt *TaxType) bool {
|
||||
if tt.EndDate.Time.IsZero() && tt.EffectiveDate.Time.Before(time.Now()) {
|
||||
return true
|
||||
}
|
||||
if tt.EndDate.Time.After(time.Now()) && tt.EffectiveDate.Time.Before(time.Now()) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
|
@ -17,6 +17,7 @@ type TaxTypeActivityWrapper struct {
|
|||
// TaxType is a first class object type
|
||||
type TaxType struct {
|
||||
ID string
|
||||
Account Account
|
||||
AccountID string
|
||||
AccountingRuleCode string
|
||||
Active bool
|
||||
|
@ -26,6 +27,7 @@ type TaxType struct {
|
|||
Category string
|
||||
CollectorDomainID string
|
||||
CompanyID string
|
||||
Contact Contact
|
||||
ContactID string
|
||||
CreatedByID string
|
||||
CreatedDate sql.NullTime
|
||||
|
@ -40,6 +42,7 @@ type TaxType struct {
|
|||
FilingPostalcode string
|
||||
FilingState string
|
||||
FilingStreet string
|
||||
Formatted taxTypeFormatted
|
||||
Fractional bool
|
||||
Frequency string
|
||||
GeocodeString string
|
||||
|
@ -67,3 +70,18 @@ type TaxType struct {
|
|||
UnitBase float64
|
||||
Units string
|
||||
}
|
||||
type taxTypeFormatted struct {
|
||||
CreatedDate string
|
||||
EffectiveDate string
|
||||
EndDate string
|
||||
Fractional string
|
||||
InterestRate string
|
||||
IsMedicinal string
|
||||
IsRecreational string
|
||||
LastModifiedDate string
|
||||
MarkupRate string
|
||||
PassThrough string
|
||||
PenaltyDays string
|
||||
PenaltyRate string
|
||||
Rate string
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue