| @@ -0,0 +1,15 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <project version="4"> | |||
| <component name="PublishConfigData" serverName="c5016" remoteFilesAllowedToDisappearOnAutoupload="false"> | |||
| <serverData> | |||
| <paths name="c5016"> | |||
| <serverdata> | |||
| <mappings> | |||
| <mapping local="$USER_HOME$/GolandProjects/SFM-loan" web="/" /> | |||
| <mapping local="$PROJECT_DIR$" web="/" /> | |||
| </mappings> | |||
| </serverdata> | |||
| </paths> | |||
| </serverData> | |||
| </component> | |||
| </project> | |||
| @@ -0,0 +1,8 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <project version="4"> | |||
| <component name="SshConfigs"> | |||
| <configs> | |||
| <sshConfig authType="OPEN_SSH" host="c5016.biukop.com.au" id="4c37c16f-8619-475c-89e3-ac3e5f71cdd1" port="22" nameFormat="DESCRIPTIVE" username="root" /> | |||
| </configs> | |||
| </component> | |||
| </project> | |||
| @@ -0,0 +1,14 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <project version="4"> | |||
| <component name="WebServers"> | |||
| <option name="servers"> | |||
| <webServer id="2d14bdeb-6cf7-4487-8af1-235dd3bc8a6f" name="c5016"> | |||
| <fileTransfer accessType="SFTP" host="c5016.biukop.com.au" port="22" sshConfigId="4c37c16f-8619-475c-89e3-ac3e5f71cdd1" sshConfig="root@c5016.biukop.com.au:22 agent" authAgent="true"> | |||
| <advancedOptions> | |||
| <advancedOptions dataProtectionLevel="Private" keepAliveTimeout="0" passiveMode="true" shareSSLContext="true" /> | |||
| </advancedOptions> | |||
| </fileTransfer> | |||
| </webServer> | |||
| </option> | |||
| </component> | |||
| </project> | |||
| @@ -44,3 +44,16 @@ func apiV1GridLoanFullOverview(w http.ResponseWriter, r *http.Request, ss *loan. | |||
| apiV1SendJson(data, w, r, ss) | |||
| } | |||
| } | |||
| func apiV1GridListLoanOverview(w http.ResponseWriter, r *http.Request, ss *loan.Session) { | |||
| input := loan.KdQueryInput{} | |||
| e := input.ReadFromHttpRequest(r) | |||
| if e != nil { | |||
| apiV1Client404Error(w, r, ss) | |||
| return | |||
| } | |||
| filter := loan.OverViewListFilter{KdQueryInput: input} | |||
| ret := filter.Retrieve() | |||
| apiV1SendJson(ret, w, r, ss) | |||
| } | |||
| @@ -46,6 +46,8 @@ func apiV1LoanSinglePostBasic(w http.ResponseWriter, r *http.Request, ss *loan.S | |||
| l.Status = input.Status | |||
| l.Amount = input.Amount | |||
| l.Item = input.Item | |||
| l.Lender = input.Lender | |||
| l.LenderLoanNumber = input.LenderLoanNumber | |||
| l.Rating = input.Rating | |||
| l.Settlement = input.Settlement | |||
| l.Description = input.Description | |||
| @@ -7,7 +7,7 @@ import ( | |||
| "net/http" | |||
| ) | |||
| func decodePayInFilter(r *http.Request) (ret loan.PayInListFilter, e error) { | |||
| func decodePayInFilter(r *http.Request) (ret loan.PayInListFilterOld, e error) { | |||
| decoder := json.NewDecoder(r.Body) | |||
| //decoder.DisallowUnknownFields() | |||
| e = decoder.Decode(&ret) | |||
| @@ -35,3 +35,15 @@ func apiV1PayInList(w http.ResponseWriter, r *http.Request, ss *loan.Session) { | |||
| apiV1SendJson(ret, w, r, ss) | |||
| } | |||
| func apiV1FilteredPayInList(w http.ResponseWriter, r *http.Request, ss *loan.Session) { | |||
| input := loan.KdQueryInput{} | |||
| e := input.ReadFromHttpRequest(r) | |||
| if e != nil { | |||
| apiV1Client404Error(w, r, ss) | |||
| return | |||
| } | |||
| payInListFilter := loan.PayInListFilter{KdQueryInput: input} | |||
| ret := payInListFilter.Retrieve() | |||
| apiV1SendJson(ret, w, r, ss) | |||
| } | |||
| @@ -0,0 +1,301 @@ | |||
| package main | |||
| import ( | |||
| "biukop.com/sfm/loan" | |||
| "encoding/json" | |||
| log "github.com/sirupsen/logrus" | |||
| "net/http" | |||
| "time" | |||
| ) | |||
| func decodeJsonPayOutEdit(r *http.Request) (ret loan.PayOut, e error) { | |||
| decoder := json.NewDecoder(r.Body) | |||
| //decoder.DisallowUnknownFields() | |||
| e = decoder.Decode(&ret) | |||
| if e != nil { | |||
| log.Error("failed decoding PayIn for updating", e.Error()) | |||
| return | |||
| } | |||
| return | |||
| } | |||
| func apiV1PayOutPost(w http.ResponseWriter, r *http.Request, ss *loan.Session) { | |||
| input, e := decodeJsonPayOutEdit(r) | |||
| log.Println(input) | |||
| if e != nil { | |||
| apiV1Client404Error(w, r, ss) | |||
| return | |||
| } else { | |||
| lowerBound, _ := time.Parse("2006-01-02", "1900-01-01") | |||
| if input.Ts.Before(lowerBound) { | |||
| input.Ts = time.Now() | |||
| } | |||
| e = input.WriteWithRewardIds() | |||
| if e != nil { | |||
| log.Error("cannot save payout meta", e.Error()) | |||
| apiV1Client404Error(w, r, ss) | |||
| } else { | |||
| poEx := loan.PayOutEx{} | |||
| e = poEx.Read(input.Id) | |||
| if e != nil { | |||
| log.Error("weird failed to read PayInEx after successfully write PayIn", input, poEx, e.Error()) | |||
| apiV1Client404Error(w, r, ss) | |||
| } else { | |||
| apiV1SendJson(poEx, w, r, ss) | |||
| } | |||
| } | |||
| } | |||
| } | |||
| func apiV1PayOutPrepared(w http.ResponseWriter, r *http.Request, ss *loan.Session) { | |||
| input, e := decodeJsonPayOutEdit(r) | |||
| log.Println(input) | |||
| if e != nil { | |||
| apiV1Client404Error(w, r, ss) | |||
| return | |||
| } | |||
| po := loan.PayOut{} | |||
| e = po.Read(input.Id) | |||
| if e != nil { | |||
| apiV1Client404Error(w, r, ss) | |||
| return | |||
| } | |||
| po.Prepared = input.Prepared | |||
| po.Approved = "" | |||
| po.Paid = "" | |||
| po.PayDate, _ = time.Parse("2006-01-02", "1900-01-01") | |||
| po.PayAmount = 0 | |||
| e = po.Write() | |||
| if e != nil { | |||
| apiV1Server500Error(w, r) | |||
| return | |||
| } | |||
| ret := loan.PayOutEx{} | |||
| e = ret.Read(input.Id) | |||
| if e != nil { | |||
| apiV1Server500Error(w, r) | |||
| return | |||
| } | |||
| apiV1SendJson(ret, w, r, ss) | |||
| } | |||
| func apiV1PayOutUnprepared(w http.ResponseWriter, r *http.Request, ss *loan.Session) { | |||
| input, e := decodeJsonPayOutEdit(r) | |||
| log.Println(input) | |||
| if e != nil { | |||
| apiV1Client404Error(w, r, ss) | |||
| return | |||
| } | |||
| po := loan.PayOut{} | |||
| e = po.Read(input.Id) | |||
| if e != nil { | |||
| apiV1Client404Error(w, r, ss) | |||
| return | |||
| } | |||
| po.Prepared = "" | |||
| po.Approved = "" | |||
| po.Paid = "" | |||
| po.PayDate, _ = time.Parse("2006-01-02", "1900-01-01") | |||
| po.PayAmount = 0 | |||
| e = po.Write() | |||
| if e != nil { | |||
| apiV1Server500Error(w, r) | |||
| return | |||
| } | |||
| ret := loan.PayOutEx{} | |||
| e = ret.Read(input.Id) | |||
| if e != nil { | |||
| apiV1Server500Error(w, r) | |||
| return | |||
| } | |||
| apiV1SendJson(ret, w, r, ss) | |||
| } | |||
| func apiV1PayOutApproved(w http.ResponseWriter, r *http.Request, ss *loan.Session) { | |||
| input, e := decodeJsonPayOutEdit(r) | |||
| log.Println(input) | |||
| if e != nil { | |||
| apiV1Client404Error(w, r, ss) | |||
| return | |||
| } | |||
| po := loan.PayOut{} | |||
| e = po.Read(input.Id) | |||
| if e != nil { | |||
| apiV1Client404Error(w, r, ss) | |||
| return | |||
| } | |||
| if po.Prepared == "" { | |||
| log.Error("try to approve unprepared payout") | |||
| apiV1Client403Error(w, r, ss) | |||
| return | |||
| } | |||
| po.Approved = input.Approved | |||
| po.Paid = "" | |||
| po.PayDate, _ = time.Parse("2006-01-02", "1900-01-01") | |||
| po.PayAmount = 0 | |||
| e = po.Write() | |||
| if e != nil { | |||
| apiV1Server500Error(w, r) | |||
| return | |||
| } | |||
| ret := loan.PayOutEx{} | |||
| e = ret.Read(input.Id) | |||
| if e != nil { | |||
| log.Error("can not approve payout ", e) | |||
| apiV1Server500Error(w, r) | |||
| return | |||
| } | |||
| apiV1SendJson(ret, w, r, ss) | |||
| } | |||
| func apiV1PayOutUnapproved(w http.ResponseWriter, r *http.Request, ss *loan.Session) { | |||
| input, e := decodeJsonPayOutEdit(r) | |||
| log.Println(input) | |||
| if e != nil { | |||
| apiV1Client404Error(w, r, ss) | |||
| return | |||
| } | |||
| po := loan.PayOut{} | |||
| e = po.Read(input.Id) | |||
| if e != nil { | |||
| apiV1Client404Error(w, r, ss) | |||
| return | |||
| } | |||
| if po.Approved == "" { | |||
| log.Error("try to unapprove draft payout") | |||
| apiV1Client403Error(w, r, ss) | |||
| return | |||
| } | |||
| po.Approved = "" | |||
| po.Paid = "" | |||
| po.PayDate, _ = time.Parse("2006-01-02", "1900-01-01") | |||
| po.PayAmount = 0 | |||
| e = po.Write() | |||
| if e != nil { | |||
| apiV1Server500Error(w, r) | |||
| return | |||
| } | |||
| ret := loan.PayOutEx{} | |||
| e = ret.Read(input.Id) | |||
| if e != nil { | |||
| log.Error("can not approve payout ", e) | |||
| apiV1Server500Error(w, r) | |||
| return | |||
| } | |||
| apiV1SendJson(ret, w, r, ss) | |||
| } | |||
| func apiV1PayOutPaid(w http.ResponseWriter, r *http.Request, ss *loan.Session) { | |||
| input, e := decodeJsonPayOutEdit(r) | |||
| log.Println(input) | |||
| if e != nil { | |||
| apiV1Client404Error(w, r, ss) | |||
| return | |||
| } | |||
| po := loan.PayOut{} | |||
| e = po.Read(input.Id) | |||
| if e != nil { | |||
| apiV1Client404Error(w, r, ss) | |||
| return | |||
| } | |||
| if po.Approved == "" || po.Prepared == "" { | |||
| log.Error("try to pay draft payout", po) | |||
| apiV1Client403Error(w, r, ss) | |||
| return | |||
| } | |||
| po.Paid = input.Paid | |||
| po.PayDate = input.PayDate | |||
| po.PayAmount = input.PayAmount | |||
| e = po.Write() | |||
| if e != nil { | |||
| apiV1Server500Error(w, r) | |||
| return | |||
| } | |||
| ret := loan.PayOutEx{} | |||
| e = ret.Read(input.Id) | |||
| if e != nil { | |||
| log.Error("can not approve payout ", e) | |||
| apiV1Server500Error(w, r) | |||
| return | |||
| } | |||
| apiV1SendJson(ret, w, r, ss) | |||
| } | |||
| func apiV1PayOutUnpaid(w http.ResponseWriter, r *http.Request, ss *loan.Session) { | |||
| input, e := decodeJsonPayOutEdit(r) | |||
| log.Println(input) | |||
| if e != nil { | |||
| apiV1Client404Error(w, r, ss) | |||
| return | |||
| } | |||
| po := loan.PayOut{} | |||
| e = po.Read(input.Id) | |||
| if e != nil { | |||
| apiV1Client404Error(w, r, ss) | |||
| return | |||
| } | |||
| if po.Approved == "" || po.Prepared == "" || po.Paid == "" { | |||
| log.Error("try to un-pay draft payout", po) | |||
| apiV1Client403Error(w, r, ss) | |||
| return | |||
| } | |||
| po.Paid = "" | |||
| po.PayDate, _ = time.Parse("2006-01-02", "1900-01-01") | |||
| po.PayAmount = 0 | |||
| e = po.Write() | |||
| if e != nil { | |||
| apiV1Server500Error(w, r) | |||
| return | |||
| } | |||
| ret := loan.PayOutEx{} | |||
| e = ret.Read(input.Id) | |||
| if e != nil { | |||
| log.Error("can not approve payout ", e) | |||
| apiV1Server500Error(w, r) | |||
| return | |||
| } | |||
| apiV1SendJson(ret, w, r, ss) | |||
| } | |||
| @@ -2,6 +2,7 @@ package main | |||
| import ( | |||
| "biukop.com/sfm/loan" | |||
| "database/sql" | |||
| log "github.com/sirupsen/logrus" | |||
| "net/http" | |||
| "strconv" | |||
| @@ -17,8 +18,13 @@ func apiV1PayOutExGet(w http.ResponseWriter, r *http.Request, ss *loan.Session) | |||
| } | |||
| e = ret.Read(int64(id)) | |||
| if e != nil { | |||
| if e == sql.ErrNoRows { | |||
| apiV1Client404Error(w, r, ss) | |||
| return | |||
| } | |||
| log.Error("failed to read PayOutEx", strId, e.Error()) | |||
| apiV1Server500Error(w, r) | |||
| return | |||
| } | |||
| apiV1SendJson(ret, w, r, ss) | |||
| @@ -61,6 +61,7 @@ func apiV1PeoplePost(w http.ResponseWriter, r *http.Request, ss *loan.Session) { | |||
| p.First = input.First | |||
| p.Last = input.Last | |||
| p.Middle = input.Middle | |||
| p.Display = input.Display | |||
| p.Enabled = input.Enabled | |||
| @@ -30,12 +30,12 @@ func apiV1RewardPost(w http.ResponseWriter, r *http.Request, ss *loan.Session) { | |||
| return | |||
| } else { | |||
| re.Id = input.Id | |||
| re.PayoutId = input.PayoutId | |||
| re.PayOutId = input.PayOutId | |||
| re.Description = input.Description | |||
| re.LoanId = input.LoanId | |||
| re.Amount = input.Amount | |||
| re.From = input.From | |||
| re.To = input.To | |||
| re.FromId = input.FromId | |||
| re.ToId = input.ToId | |||
| re.Ts = input.Ts | |||
| e = re.Write() | |||
| if e != nil { | |||
| @@ -64,3 +64,16 @@ func apiV1RewardDelete(w http.ResponseWriter, r *http.Request, ss *loan.Session) | |||
| } | |||
| apiV1SendJson(id64, w, r, ss) | |||
| } | |||
| func apiV1RewardExListPost(w http.ResponseWriter, r *http.Request, ss *loan.Session) { | |||
| input := loan.KdQueryInput{} | |||
| e := input.ReadFromHttpRequest(r) | |||
| if e != nil { | |||
| apiV1Client404Error(w, r, ss) | |||
| return | |||
| } | |||
| rewardListFilter := loan.RewardExListFilter{KdQueryInput: input} | |||
| ret := rewardListFilter.Retrieve() | |||
| apiV1SendJson(ret, w, r, ss) | |||
| return | |||
| } | |||
| @@ -163,3 +163,13 @@ func apiV1UserExGet(w http.ResponseWriter, r *http.Request, ss *loan.Session) { | |||
| } | |||
| apiV1SendJson(ret, w, r, ss) | |||
| } | |||
| func apiV1UserExList(w http.ResponseWriter, r *http.Request, ss *loan.Session) { | |||
| filter := "" | |||
| keys, ok := r.URL.Query()["filter"] | |||
| if ok && len(keys) >= 1 { | |||
| filter = keys[0] | |||
| } | |||
| data := loan.GetUserExList(filter) | |||
| apiV1SendJson(data, w, r, ss) | |||
| } | |||
| @@ -35,7 +35,8 @@ func setupApiV1Handler() []apiV1HandlerMap { | |||
| {"GET", "chart/past-year-monthly", apiV1ChartPastYearMonthly}, | |||
| {"GET", "chart/recent-10-loans", apiV1ChartRecent10Loans}, | |||
| {"GET", "chart/top-broker", apiV1ChartTopBroker}, | |||
| {"POST", "grid/loan/full-loan-overview", apiV1GridLoanFullOverview}, | |||
| //{"POST", "grid/loan/full-loan-overview", apiV1GridLoanFullOverview}, | |||
| {"POST", "grid/loan/full-loan-overview", apiV1GridListLoanOverview}, | |||
| {"GET", "chart/reward-vs-income-monthly", apiV1ChartRewardVsIncomeMonthly}, | |||
| {"GET", "loan/", apiV1LoanSingleGet}, | |||
| {"DELETE", "loan/", apiV1LoanSingleDelete}, | |||
| @@ -53,6 +54,7 @@ func setupApiV1Handler() []apiV1HandlerMap { | |||
| {"POST", "user-enable/", apiV1UserEnable}, | |||
| {"GET", "user-ex/", apiV1UserExGet}, | |||
| {"GET", "user-ex-list/", apiV1UserExList}, | |||
| {"GET", "broker/", apiV1BrokerGet}, | |||
| {"POST", "broker/", apiV1BrokerPost}, | |||
| @@ -66,12 +68,14 @@ func setupApiV1Handler() []apiV1HandlerMap { | |||
| {"POST", "reward/", apiV1RewardPost}, | |||
| {"DELETE", "reward/", apiV1RewardDelete}, | |||
| {"GET", "people-list/", apiV1PeopleList}, | |||
| {"GET", "broker-list/", apiV1BrokerList}, | |||
| {"POST", "sync-people/", apiV1SyncPeople}, | |||
| {"POST", "payIn/", apiV1PayInPost}, | |||
| {"DELETE", "payIn/", apiV1PayInDelete}, | |||
| {"POST", "pay-in-list/", apiV1PayInList}, | |||
| {"POST", "pay-in-filtered-list/", apiV1FilteredPayInList}, | |||
| {"GET", "user-reward/", apiV1UserReward}, | |||
| {"GET", "login-available/", apiV1LoginAvailable}, | |||
| @@ -95,6 +99,16 @@ func setupApiV1Handler() []apiV1HandlerMap { | |||
| {"GET", "payout-ex/", apiV1PayOutExGet}, | |||
| {"POST", "reward-ex-list/", apiV1RewardExListPost}, | |||
| {"POST", "payout/", apiV1PayOutPost}, | |||
| {"POST", "payout-prepared/", apiV1PayOutPrepared}, | |||
| {"POST", "payout-unprepared/", apiV1PayOutUnprepared}, | |||
| {"POST", "payout-approved/", apiV1PayOutApproved}, | |||
| {"POST", "payout-unapproved/", apiV1PayOutUnapproved}, | |||
| {"POST", "payout-paid/", apiV1PayOutPaid}, | |||
| {"POST", "payout-unpaid/", apiV1PayOutUnpaid}, | |||
| {"GET", "login", apiV1DumpRequest}, | |||
| } | |||
| } else { //production | |||
| @@ -106,7 +120,8 @@ func setupApiV1Handler() []apiV1HandlerMap { | |||
| {"GET", "chart/past-year-monthly", apiV1ChartPastYearMonthly}, | |||
| {"GET", "chart/recent-10-loans", apiV1ChartRecent10Loans}, | |||
| {"GET", "chart/top-broker", apiV1ChartTopBroker}, | |||
| {"POST", "grid/loan/full-loan-overview", apiV1GridLoanFullOverview}, | |||
| //{"POST", "grid/loan/full-loan-overview", apiV1GridLoanFullOverview}, | |||
| {"POST", "grid/loan/full-loan-overview", apiV1GridListLoanOverview}, | |||
| {"GET", "chart/reward-vs-income-monthly", apiV1ChartRewardVsIncomeMonthly}, | |||
| {"GET", "loan/", apiV1LoanSingleGet}, | |||
| {"DELETE", "loan/", apiV1LoanSingleDelete}, | |||
| @@ -124,6 +139,7 @@ func setupApiV1Handler() []apiV1HandlerMap { | |||
| {"POST", "user-enable/", apiV1UserEnable}, | |||
| {"GET", "user-ex/", apiV1UserExGet}, | |||
| {"GET", "user-ex-list/", apiV1UserExList}, | |||
| {"GET", "broker/", apiV1BrokerGet}, | |||
| {"POST", "broker/", apiV1BrokerPost}, | |||
| @@ -138,12 +154,14 @@ func setupApiV1Handler() []apiV1HandlerMap { | |||
| {"POST", "reward/", apiV1RewardPost}, | |||
| {"DELETE", "reward/", apiV1RewardDelete}, | |||
| {"GET", "people-list", apiV1PeopleList}, | |||
| {"GET", "broker-list/", apiV1BrokerList}, | |||
| {"POST", "sync-people/", apiV1SyncPeople}, | |||
| {"POST", "payIn/", apiV1PayInPost}, | |||
| {"DELETE", "payIn/", apiV1PayInDelete}, | |||
| {"POST", "pay-in-list/", apiV1PayInList}, | |||
| {"POST", "pay-in-filtered-list/", apiV1FilteredPayInList}, | |||
| {"GET", "user-reward/", apiV1UserReward}, | |||
| {"GET", "login-available/", apiV1LoginAvailable}, | |||
| @@ -167,6 +185,16 @@ func setupApiV1Handler() []apiV1HandlerMap { | |||
| {"GET", "payout-ex/", apiV1PayOutExGet}, | |||
| {"POST", "reward-ex-list/", apiV1RewardExListPost}, | |||
| {"POST", "payout/", apiV1PayOutPost}, | |||
| {"POST", "payout-prepared/", apiV1PayOutPrepared}, | |||
| {"POST", "payout-unprepared/", apiV1PayOutUnprepared}, | |||
| {"POST", "payout-approved/", apiV1PayOutApproved}, | |||
| {"POST", "payout-unapproved/", apiV1PayOutUnapproved}, | |||
| {"POST", "payout-paid/", apiV1PayOutPaid}, | |||
| {"POST", "payout-unpaid/", apiV1PayOutUnpaid}, | |||
| {"GET", "login", apiV1EmptyResponse}, | |||
| } | |||
| } | |||