v0.1.36
Vernon Keenan 2021-01-27 14:39:23 -08:00
parent f9bf88c55f
commit b61112d1e3
11 changed files with 461 additions and 0 deletions

25
app/account-cache.go Normal file
View File

@ -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
}

47
app/account-services.go Normal file
View File

@ -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
app/company-services.go Normal file
View File

29
app/county-cache.go Normal file
View File

@ -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
}

58
app/county-services.go Normal file
View File

@ -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
}

29
app/place-cache.go Normal file
View File

@ -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
}

62
app/place-services.go Normal file
View File

@ -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
}

View File

@ -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) {

25
app/taxtype-cache.go Normal file
View File

@ -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
}

162
app/taxtype-services.go Normal file
View File

@ -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
}

View File

@ -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
}