12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import base64
- import datetime
- import logging
- import random
- import re
- import time
- import urlparse
- import uuid
- from collections import Counter, defaultdict
- from decimal import Decimal
- from itertools import groupby
- from operator import itemgetter
- import arrow
- import cytoolz
- import simplejson as json
- from bson import Regex
- from bson.objectid import ObjectId
- from dateutil.relativedelta import relativedelta
- from django.conf import settings
- from django.contrib import auth
- from django.contrib.auth.hashers import make_password
- from django.core.cache import caches
- from django.core.handlers.wsgi import WSGIRequest
- from django.http import HttpResponse
- from django.views.decorators.http import require_POST, require_GET
- from mongoengine import Q
- from mongoengine.errors import DoesNotExist, NotUniqueError
- from typing import TYPE_CHECKING, Optional, cast, Union, Dict, Mapping
- from voluptuous import MultipleInvalid
- from apilib import utils_datetime
- from apilib.monetary import RMB, VirtualCoin, sum_rmb
- from apilib.quantity import Quantity
- from apilib.utils import natural_sort, is_number, round_2_digits
- from apilib.utils_datetime import to_datetime, defaultTodayDate, dt_to_timestamp, get_zero_time, \
- get_tomorrow_zero_time
- from apilib.utils_datetime import today_datetime_range
- from apilib.utils_json import JsonResponse, json_dumps
- from apilib.utils_mongo import format_dot_key
- from apilib.utils_string import cn
- from apilib.utils_url import add_query
- from apps import serviceCache, reportCache
- from apps.common.utils import get_start_and_end_by_month, get_start_and_end_by_year, get_date_range
- from apps.thirdparties.aliyun import AliyunSlider
- from apps.web.agent.models import Agent
- from apps.web.api.models import APIStartDeviceRecord
- from apps.web.common.models import District, DEFAULT_DEALER_FEATURES, WithdrawRecord, OperatorLog, \
- MonthlyPackageTemp, WithdrawBankCard
- from apps.web.common.proxy import ClientRechargeModelProxy, ClientConsumeModelProxy, DealerDailyStatsModelProxy, \
- GroupDailyStatsModelProxy, DeviceDailyStatsModelProxy, ClientDealerIncomeModelProxy, DealerReportModelProxy
- from apps.web.common.transaction import WithdrawStatus, WITHDRAW_PAY_TYPE, translate_withdraw_state
- from apps.web.common.transaction.pay import OrderCacheMgr, PayManager
- from apps.web.common.transaction.refund import RefundManager
- from apps.web.common.validation import NAME_RE, PHONE_NUMBER_RE
- from apps.web.constant import (
- Const,
- DEALER_CONSUMPTION_AGG_KIND_TRANSLATION,
- DEALER_CONSUMPTION_AGG_KIND, DEALER_CONSUMPTION_AGG_KIND_UNIT,
- MONTH_DATE_KEY,
- FAULT_RECORD_STATUS, APP_TYPE, PollRecordDefine, TYPE_ADJUST_USER_VIRTUAL_CARD, DeviceCmdCode,
- ErrorCode, RECHARGE_CARD_TYPE, RECHARGE_RECORD_VIA_TRANSLATION, skip_package_unit_verify_list,
- skip_package_range_verify_list, skip_package_params_verify_list, USER_RECHARGE_TYPE, CONSUMETYPE,
- support_policy_weifule, support_policy_device)
- from apps.web.constant import RechargeRecordVia
- from apps.web.core import PayAppType, ROLE
- from apps.web.core.accounting import Accounting, devCoinTmpl
- from apps.web.core.auth.wechat import WechatAuthBridge
- from apps.web.core.bridge.wechat import WechatClientProxy
- from apps.web.core.db import paginate, prepare_query, search_query
- from apps.web.core.device_define.huopo import HuopoCacheMgr
- from apps.web.core.exceptions import ServiceException, InvalidParameter, ParameterError, InvalidFileSize, \
- InvalidFileName, RentDeviceError
- from apps.web.core.file import AliOssFileUploader, SwapGroupPicFileUploader
- from apps.web.core.helpers import ActionDeviceBuilder
- from apps.web.core.messages.sms import (
- dealerAutoWithdrawSMSProvider,
- dealerRegisterSMSProvider,
- dealerWithdrawSMSProvider,
- dealerBindWechatSMSProvider,
- dealerBindWalletWechatSMSProvider,
- dealerEditMonitorSMSProvider,
- dealerMonitorWithdrawSMSProvider)
- from apps.web.core.models import OfflineTask, WechatPayApp
- from apps.web.core.networking import MessageSender
- from apps.web.core.payment import WithdrawGateway, PaymentGateway
- from apps.web.core.payment.wechat import WechatPaymentGateway
- from apps.web.core.sysparas import SysParas
- from apps.web.core.utils import DefaultJsonErrorResponse, JsonErrorResponse, JsonOkResponse, parse_json_payload
- from apps.web.dealer import OfflineTaskType
- from apps.web.dealer.define import DEALER_INCOME_SOURCE, DEALER_INCOME_SOURCE_TRANSLATION, DEALER_INCOME_TYPE, \
- PAY_NOTIFY_URL, DEALER_BIND_WECHAT_URL, DEALER_BIND_WALLET_WECHAT_URL
- from apps.web.dealer.models import (
- Dealer, UpscoreRecord, DealerRechargeRecord,
- OnSale, OnSaleRecord, VirtualCard,
- ElecPriceTemplate, ItemType,
- SubAccount, DealerMessage, Complaint, AdjustUserVirtualCardRecord, ExchangeOrder, DealerAddr, UpCardScoreRecord,
- PermissionRole, PermissionRule, TodoMessage, ApiAppInfo, RefundDealerRechargeRecord)
- from apps.web.dealer.proxy import DealerIncomeProxy
- from apps.web.dealer.transaction import post_pay
- from apps.web.dealer.transaction_deprecated import refund_post_pay
- from apps.web.dealer.utils import gen_login_response, gen_home_response, gen_subaccount_login_response, \
- VirtualCardBuilder, create_dealer_sim_charge_order, DealerSessionBuilder, MyToken, \
- create_dealer_charge_order_for_api, create_dealer_charge_order_for_disable_ad
- from apps.web.dealer.validation import dealerSchema
- from apps.web.dealer.validator import UserListValidator
- from apps.web.dealer.withdraw import DealerWithdrawService
- from apps.web.device.define import DeviceChannelType
- from apps.web.device.models import Device, Group, FeedBack, DeviceType, StockRecord, Cell, FaultRecord, Part, Battery, \
- GroupDict, DeviceRentOrder, GroupCacheMgr
- from apps.web.device.models import DeviceDict, RequestBodyDict, SwapGroup, DiscountPriceCharging, PriceCharging, \
- ChargeTag, Picture
- from apps.web.device.timescale import SignalManager
- from apps.web.device.utils import device_control_cache_key
- from apps.web.exceptions import UserServerException
- from apps.web.helpers import get_wx_config, current_platform, get_app, \
- get_wechat_auth_bridge, \
- get_wechat_user_manager_mp_proxy, \
- remove_some_desc_for_consume, get_inhourse_wechat_env_pay_gateway
- from apps.web.management.models import Manager
- from apps.web.report.models import (
- DevReport, GroupReport, DealerReport,
- GroupDailyStat, DealerMonthlyStat, DealerDailyStat, DeviceDailyStat
- )
- from apps.web.report.utils import (
- consumption_unit_precision,
- to_quantity,
- translate_income,
- translate_consumption)
- from apps.web.south_intf.swap_carcharger import SwapContract
- from apps.web.south_intf.zhejiang_fire import Company
- from apps.web.south_intf.zhejiang_fire import handler_event_to_zhejiang
- from apps.web.user.models import RechargeRecord, ConsumeRecord, MyUser, CardConsumeRecord, Card, \
- CardRechargeRecord, CardRechargeOrder, UserVirtualCard, ServiceProgress, VirtualCardRechargeRecord, BlackListUsers, \
- SwapCardRecord, UniqueUser
- from apps.web.user.transaction_deprecated import refund_cash
- from apps.web.user.utils import check_black_user, BatteryInfo
- from apps.web.user.utils2 import get_paginate
- from apps.web.utils import (permission_required, LimitAttemptsManager,
- dealer_login, subAccount_login, error_tolerate,
- ensure_all_fields_are_not_empty,
- is_login, check_role, is_dealer, concat_server_end_url,
- ErrorResponseRedirect,
- FrontEndResponseRedirect, ExternalResponseRedirect, DealerBindIdResponseRedirect,
- ViewValidator, record_operation_behavior)
- from apps.web.wrapper import request_limit_by_user
- from library.wechatbase.exceptions import WeChatException
- from taskmanager.mediator import task_caller
- logger = logging.getLogger(__name__)
- merge_with = cytoolz.merge_with
- get_in = cytoolz.get_in
- if TYPE_CHECKING:
- from apps.web.core.db import CustomQuerySet
- from collections import Iterable
- from apps.web.core.db import Query
- from apps.web.common.models import UserSearchable
- from apps.web.core.adapter.bolai_gateway import ChargingGatewayBox
- from apps.web.core.adapter.bolai_node import ChargingBox
- from apps.web.core.adapter.huiteng import washerHTBox
- from apps.web.core.adapter.xiyiji import WasherBox
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getCheckCodeForNewTel(request):
- # type: (WSGIRequest)->JsonResponse
- payload = json.loads(request.body)
- toNumber = payload.get('phone', None)
- agentId = request.user.agentId
- agent = Agent.get_agent(agentId)
- productName = agent['productName']
- status, msg = dealerRegisterSMSProvider.get(phoneNumber = toNumber,
- productName = productName,
- vendor = SysParas.get_sms_vendor(request.user.smsVendor))
- if not status:
- return JsonResponse({'result': 0, 'description': msg})
- else:
- return JsonResponse({'result': 1, 'description': ''})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- def getCheckCode(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 经销商获取注册短信验证码
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- toNumber = payload.get('phone', None)
- agentId = request.COOKIES.get('agentId', settings.MY_PRIMARY_AGENT_ID)
- agent = Agent.objects(id = agentId).first() # type: Agent
- sessionId = payload.get('csessionid', None)
- sig = payload.get('sig', None)
- token = payload.get('nc_token', None)
- result = eval(AliyunSlider().check_validation_results(sessionId, sig, token))
- if type(result) is dict:
- resultCode = result.get('Code', 900)
- else:
- resultCode = 900
- if resultCode == 100:
- status, msg = dealerRegisterSMSProvider.get(phoneNumber = toNumber,
- productName = agent.productName,
- vendor = SysParas.get_sms_vendor(agent.smsVendor))
- if not status:
- return JsonResponse({'result': 0, 'description': msg})
- else:
- return JsonResponse({'result': 1, 'description': ''})
- else:
- return JsonResponse({'result': 0, 'description': u'非正常请求,验证码发送失败'})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- def verifyForgetCode(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 经销商验证短信验证码
- :param request:
- :return:
- """
- phone = request.POST.get('phone', None)
- code = request.POST.get('code', None)
- password = request.POST.get('password', "")
- agentId = request.POST.get('agentId')
- if not agentId:
- return JsonErrorResponse(u'未选择您对应的代理商,请刷新后再试')
- dealer = Dealer.objects(username=phone, agentId=agentId).first()
- while True:
- if dealer is None:
- response = JsonErrorResponse(u'该手机号尚未注册,请注册后再进行操作')
- break
- if password == "":
- response = JsonErrorResponse(u"请输入密码")
- break
- status, desc = dealerRegisterSMSProvider.verify(phone, code)
- if not status:
- response = JsonErrorResponse(desc)
- else:
- dealer.set_password(password)
- dealer.unlock_login()
- response = JsonResponse({"result": 1, "description": None, "payload": {}})
- break
- if agentId != request.COOKIES.get('agentId'):
- Agent.record_cookie(agentId, response)
- return response
- @error_tolerate(nil=DefaultJsonErrorResponse)
- def getSubAccountCheckCode(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 经销商获取注册短信验证码
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- toNumber = payload.get('phone', None)
- agentId = request.COOKIES.get('agentId', settings.MY_PRIMARY_AGENT_ID)
- agent = Agent.objects(id = agentId).first() # type: Agent
- sessionId = payload.get('csessionid', None)
- sig = payload.get('sig', None)
- token = payload.get('nc_token', None)
- result = eval(AliyunSlider().check_validation_results(sessionId, sig, token))
- if type(result) is dict:
- resultCode = result.get('Code', 900)
- else:
- resultCode = 900
- if resultCode == 100:
- status, msg = dealerRegisterSMSProvider.get(phoneNumber = toNumber,
- productName = agent.productName,
- vendor = SysParas.get_sms_vendor(agent.smsVendor))
- if not status:
- return JsonResponse({'result': 0, 'description': msg})
- else:
- return JsonResponse({'result': 1, 'description': ''})
- else:
- return JsonResponse({'result': 0, 'description': u'非正常请求,验证码发送失败'})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- def verifySubAccountForgetCode(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 经销商验证短信验证码
- :param request:
- :return:
- """
- phone = request.POST.get('phone', None)
- code = request.POST.get('code', None)
- password = request.POST.get('password', "")
- agentId = request.POST.get('agentId')
- if not agentId:
- return JsonErrorResponse(u'未选择您对应的代理商,请刷新后再试')
- subaccount = SubAccount.objects(username=phone, agentId=agentId).first()
- while True:
- if subaccount is None:
- response = JsonErrorResponse(u'该手机号不是子账号,请主账号添加此子账号后再进行操作')
- break
- if password == "":
- response = JsonErrorResponse(u"请输入密码")
- break
- status, desc = dealerRegisterSMSProvider.verify(phone, code)
- if not status:
- response = JsonErrorResponse(desc)
- else:
- subaccount.set_password(password)
- subaccount.unlock_login()
- response = JsonResponse({"result": 1, "description": None, "payload": {}})
- break
- if agentId != request.COOKIES.get('agentId'):
- Agent.record_cookie(agentId, response)
- return response
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试'))
- def getDealerRegisterSMSCode(request):
- # type: (WSGIRequest)->JsonResponse
- payload = json.loads(request.body)
- phoneNumber = payload.get('phoneNumber', None)
- agentId = request.COOKIES.get('agentId', settings.MY_PRIMARY_AGENT_ID)
- agent = Agent.objects(id = agentId).first() # type: Agent
- sessionId = payload.get('csessionid', None)
- sig = payload.get('sig', None)
- token = payload.get('nc_token', None)
- result = eval(AliyunSlider().check_validation_results(sessionId, sig, token))
- if type(result) is dict:
- resultCode = result.get('Code', 900)
- else:
- resultCode = 900
- if not phoneNumber:
- return JsonResponse({'result': 0, 'description': u'手机号码为空'})
- if len(Dealer.objects.filter(username = phoneNumber, agentId = agentId)):
- return JsonResponse({'result': 0, 'description': u'该手机号已注册'})
- if resultCode == 100:
- status, msg = dealerRegisterSMSProvider.get(phoneNumber = phoneNumber,
- productName = agent.productName,
- vendor = SysParas.get_sms_vendor(agent.smsVendor))
- if not status:
- return JsonResponse({'result': 0, 'description': msg})
- else:
- return JsonResponse({'result': 1, 'description': ''})
- else:
- return JsonResponse({'result': 0, 'description': u'非正常请求,验证码发送失败'})
- def dealerRegister(request):
- # type: (WSGIRequest)->JsonResponse
- try:
- rawPayload = json.loads(request.body) # type: dict
- mid = rawPayload.pop('managerId', None)
- if mid:
- agentId = Manager.objects.get(id=ObjectId(mid)).primeAgentId
- rawPayload['agentId'] = str(agentId)
- else:
- agentId = rawPayload.pop('agentId', None)
- if agentId:
- rawPayload['agentId'] = str(agentId)
- try:
- payload = dealerSchema(rawPayload)
- except MultipleInvalid:
- return JsonErrorResponse(description=u'信息填入有误,请检查手机号码等信息是否合法')
- agentId = rawPayload.get('agentId')
- agent = Agent.objects(id=agentId).first() # type: Optional[Agent]
- if not agent:
- return JsonErrorResponse(description=u'请联系您的代理商获取正确的经销商注册地址')
- username = payload.pop('username').strip()
- password = payload.pop('password').strip()
- if PHONE_NUMBER_RE.match(username) is None:
- return JsonErrorResponse(description=u'请输入正确格式的手机号码')
- status, msg = dealerRegisterSMSProvider.verify(phoneNumber=username, smsCode=rawPayload["code"])
- if not status:
- return JsonErrorResponse(description=msg)
- payload['features'] = DEFAULT_DEALER_FEATURES
-
- try:
- Dealer.create_user(
- username = username,
- password = password,
- adShow = True,
- noAdPolicy = 'banner',
- annualTrafficCost = agent.annualTrafficCost if \
- agent.annualTrafficCost > agent.trafficCardCost else agent.trafficCardCost,
- trafficCardCost = agent.trafficCardCost,
- withdrawFeeRatio = agent.withdrawFeeRatio if \
- agent.withdrawFeeRatio > agent.withdrawFeeRatioCost else agent.withdrawFeeRatioCost,
- **payload
- )
- except NotUniqueError:
- return JsonErrorResponse(description=u'该经销商已注册')
- except MultipleInvalid as e:
- logger.exception('failed to validate register dealer payload due to %s' % e)
- return JsonErrorResponse(description=u'部分输入不合法,请重试')
- except Exception as e:
- logger.exception('cannot register dealer due to %s' % e)
- return JsonErrorResponse(description=u'注册失败请重试')
- return JsonOkResponse()
- def dealerAccess(request):
- # type: (WSGIRequest)->JsonResponse
- agentId = request.GET.get('agentId', '')
- if not is_login(request, ROLE.dealer):
- response = gen_login_response(agentId)
- else:
- agent = Agent.objects(id=str(request.user.agentId)).get()
- if (not agentId) or (agentId == request.user.agentId) or (agentId == str(agent.primary_agent.id)):
- agentId = request.user.agentId
- response = gen_home_response(agentId)
- else:
- response = gen_login_response(agentId)
- return response
- def subAccountAccess(request):
- agentId = request.GET.get('agentId', '')
- if not is_login(request, ROLE.subaccount):
- response = gen_subaccount_login_response(agentId)
- else:
- agent = Agent.objects(id=str(request.user.agentId)).get()
- if (not agentId) or (agentId == request.user.agentId) or (agentId == str(agent.primary_agent.id)):
- agentId = request.user.agentId
- response = gen_home_response(agentId)
- else:
- response = gen_subaccount_login_response(agentId)
- return response
- def login(request):
- # type: (WSGIRequest)->JsonResponse
- username = request.POST.get('name', None)
- password = request.POST.get('password', None)
- agentId = request.POST.get('agentId')
- if not agentId:
- return JsonResponse({'result': 100, 'description': u'未选择对应的代理商,请刷新后在试', 'payload': {}})
- if not all([username, password]):
- response = JsonResponse({'result': 0, 'description': u'缺少用户名或密码', 'payload': {}})
- else:
- response = dealer_login(request, logger, username, password, agentId=agentId)
- if agentId != request.COOKIES.get('agentId', None):
- Agent.record_cookie(agentId, response)
- return response
- def subAccountLogin(request):
- username = request.POST.get('name', None)
- password = request.POST.get('password', None)
- agentId = request.POST.get('agentId')
- if not all([username, password]):
- response = JsonResponse({'result': 0, 'description': u'缺少用户名或密码', 'payload': {}})
- else:
- response = subAccount_login(request, logger, username, password, agentId=agentId)
- if agentId != request.COOKIES.get('agentId', None):
- Agent.record_cookie(agentId, response)
- response.set_cookie(key='sub_account_login_agentid', value=str(agentId), max_age=24 * 3600 * 30, domain = settings.COOKIE_DOMAIN)
- return response
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def homepageData(request):
- # type: (WSGIRequest)->JsonResponse
- currentDealer = request.user # type: Optional[Dealer, SubAccount]
- dealer = request.user.myBoss # type: Dealer
-
- # 显示经销商的总余额(资金池+消费分润) 分两级显示
- deviceBalance = dealer.sub_balance(DEALER_INCOME_TYPE.DEVICE_INCOME)
- ledgerBalance = dealer.sub_balance(DEALER_INCOME_TYPE.LEDGER_CONSUME)
- payload = {
- 'totalBalance': deviceBalance + ledgerBalance,
- 'deviceBalance': deviceBalance,
- 'ledgerBalance': ledgerBalance
- }
- groupIds = Group.get_group_ids_of_dealer(str(dealer.id))
- partnerGroupIds = Group.get_group_ids_of_partner(str(dealer.id))
- groupIds.extend(partnerGroupIds)
- devList = Device.get_devices_by_group(groupIds).values()
- offlineCount, expireCount, allCount = 0, 0, 0
- for dev in devList: # type: DeviceDict
- allCount += 1
- if not dev.online:
- offlineCount += 1
- if dev.is_authorized_to_dealer(str(dealer.id)) and (dev.sim_expire_notify or dev.is_expired):
- expireCount += 1
- onlineCount = allCount - offlineCount
- payload.update({'onlineCount': onlineCount, 'offlineCount': offlineCount})
- payload['adShow'] = currentDealer.adShow
- payload['feedback'] = FeedBack.get_unhandled_count(ownerId=str(dealer.id))
- if expireCount > 0:
- payload['simCardTip'] = {
- 'expireCount': expireCount,
- 'todoMsg': TodoMessage.sim_expire_message(str(currentDealer.id), expireCount)
- }
- payload['pushBrokerUrl'] = currentDealer.pushBrokerUrl
- payload['isPurePartner'] = currentDealer.isPurePartner
- payload['inhouseApp'] = currentDealer.is_inhouse_wallet
- # 获取agent的相关信息
- resultResponse = JsonResponse({'result': 1, 'description': None, 'payload': payload})
- resultResponse = Agent.record_cookie(currentDealer.agentId, resultResponse)
- return resultResponse
- @error_tolerate(nil=JsonErrorResponse(u'上分失败,请重试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def onPoints(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 远程上分, 支持经销商和代理商进行操作,代理商通过上分测试机器系统流程正确。
- :param request:
- :return:
- """
- TYPE_POINTS = ''
- TYPE_CHARGE_CARD = 'chargeCard'
- def __points__(dev, ruleId):
- smartBox = ActionDeviceBuilder.create_action_device(dev)
- if dev.support_reliable:
- orderNo = dev.ownerId[-10:]+ConsumeRecord.make_no()
- order = ConsumeRecord(orderNo=orderNo, openId=dev.ownerId)
- order.package = dev.get('washConfig',{}).get(ruleId)
- order.attachParas = attachParas
- smartBox.start_device_realiable(order)
- lineInfo = {'port':attachParas.get('chargeIndex'), 'status':Const.DEV_WORK_STATUS_WORKING}
- Device.update_port_control_cache(dev.devNo, lineInfo)
- else:
- smartBox.start(ruleId, openId = None, attachParas = attachParas)
- address = Group.get_group(dev['groupId'])['address']
- groupName = Group.get_group(dev['groupId'])['groupName']
- score = dev.get('washConfig', {}).get(ruleId, {}).get('coins', 0)
- UpscoreRecord(
- logicalCode=dev['logicalCode'],
- devNo=devNo,
- ownerId=ownerId,
- time=datetime.datetime.now(),
- score=score,
- address=address,
- groupName=groupName,
- devType=dev['devType']['name'],
- type=TYPE_POINTS
- ).save()
- def __charge_card(dev, price):
- smartBox = ActionDeviceBuilder.create_action_device(dev)
- smartBox.remote_charge_card(price)
- address = Group.get_group(dev['groupId'])['address']
- groupName = Group.get_group(dev['groupId'])['groupName']
- UpscoreRecord(
- logicalCode=dev['logicalCode'],
- devNo=devNo,
- ownerId=ownerId,
- time=datetime.datetime.now(),
- score=price,
- address=address,
- groupName=groupName,
- devType=dev['devType']['name'],
- type=TYPE_CHARGE_CARD
- ).save()
- def __huopo_points(dev):
- ruleId = "1"
- smartBox = ActionDeviceBuilder.create_action_device(dev)
- smartBox.start(ruleId, openId = None, attachParas = attachParas)
- address = Group.get_group(dev['groupId'])['address']
- groupName = Group.get_group(dev['groupId'])['groupName']
- score = 0
- UpscoreRecord(
- logicalCode=dev['logicalCode'],
- devNo=devNo,
- ownerId=ownerId,
- time=datetime.datetime.now(),
- score=score,
- address=address,
- groupName=groupName,
- devType=dev['devType']['name'],
- type=TYPE_POINTS
- ).save()
- def __policy_points__(dev, ruleId):
- smartBox = ActionDeviceBuilder.create_action_device(dev)
- if dev.support_reliable:
- orderNo = dev.ownerId[-10:]+ConsumeRecord.make_no()
- order = ConsumeRecord(orderNo=orderNo, openId=dev.ownerId)
- order.package = smartBox.prepare_package(ruleId, attachParas)
- order.attachParas = attachParas
- smartBox.start_device_realiable(order)
- lineInfo = {
- 'port': attachParas.get('chargeIndex'),
- 'status': Const.DEV_WORK_STATUS_WORKING,
- 'nickName': '经销商远程上分',
- 'startTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- }
- data = smartBox._check_package(order.package)
- if 'needTime' in data:
- lineInfo.update({'needTime': data['needTime']})
- if 'needElec' in data:
- lineInfo.update({'needElec': data['needElec']})
- Device.update_port_control_cache(dev.devNo, lineInfo)
- address = Group.get_group(dev['groupId'])['address']
- groupName = Group.get_group(dev['groupId'])['groupName']
- UpscoreRecord(
- logicalCode=dev['logicalCode'],
- devNo=devNo,
- ownerId=ownerId,
- time=datetime.datetime.now(),
- package=order.package,
- address=address,
- groupName=groupName,
- devType=dev['devType']['name'],
- type=TYPE_POINTS
- ).save()
- try:
- ownerId = str(request.user.bossId)
- logicalCode = request.POST.get('logicalCode', None)
- attachParas = json.loads(request.POST.get('attachParas', '{}'))
- attachParas['onPoints'] = True
- type = request.POST.get('type', '')
- devNo = Device.get_devNo_by_logicalCode(logicalCode)
- dev = Device.get_dev(devNo)
- if not dev:
- return JsonResponse({'result': 2, 'description': u'设备不存在'})
- if dev['ownerId'] != ownerId:
- return JsonResponse({'result': 2, 'description': u'不是你家设备,不能操作喔'})
- dealer = dev.owner
- agent = Agent.objects.filter(id=str(dealer.agentId)).first() # type: Agent
- if 'disable_dealer_onPoints_and_sendCoins' in agent.features:
- return JsonResponse(
- {'result': 0, 'description': '设备无法使用该功能奥, 如有问题, 请联系代理商', 'payload': {}})
- # 霍珀的道闸适配
- if dev["devType"]["code"] == Const.DEVICE_TYPE_CODE_HP_GATE:
- __huopo_points(dev)
- return JsonResponse({'result': 1, 'description': u'success'})
- if dev["devType"]["code"] in support_policy_device:
- ruleId = request.POST.get('ruleId', None)
- __policy_points__(dev, ruleId)
- return JsonResponse({'result': 1, 'description': u'success'})
- if type == TYPE_POINTS:
- ruleId = request.POST.get('ruleId', None)
- # 如果是串口设备,上分的话,直接使用套餐。这里把串口和非串口的上分统一起来,行为应该有创建者创建具备行为的实例
- if not ruleId:
- return JsonResponse(
- {'result': 0, 'description': u'没有找到对应的套餐信息,请您重新选择其他分值.或者检查设备是否没有注册到系统', 'payload': {}})
- __points__(dev, ruleId)
- elif type == TYPE_CHARGE_CARD:
- price = int(request.POST.get('coins', 0))
- if price <= 0:
- return JsonResponse({'result': 0, 'description': u'充值金额错,请重新输入', 'payload': {}})
- __charge_card(dev, price)
- return JsonResponse({'result': 1, 'description': u'success'})
- except ServiceException, e:
- logger.exception(e)
- return JsonResponse(e.result)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def onPointsRecords(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 上分记录查询
- :param request:
- :return:
- """
- ownerId = str(request.user.bossId)
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- objs = UpscoreRecord.objects.filter(ownerId=ownerId).order_by('-time')
- rcdList = []
- total = 0
- sumCoins = 0
- sumCoinsTotal = 0
- sumCharge = 0
- sumChargeTotal = 0
- for obj in objs:
- if obj.type == 'chargeCard':
- sumCharge += obj.score
- sumChargeTotal += 1
- else:
- sumCoins += obj.score
- sumCoinsTotal += 1
- total += 1
- rcdList.append({
- 'logicalCode': obj.logicalCode,
- 'devNo': obj.devNo,
- 'createdStr': obj.time.strftime('%Y-%m-%d %H:%M:%S'),
- 'coins': obj.score,
- 'et_type_name': obj.devType,
- 'address': obj.address,
- 'groupName': obj.groupName,
- 'type': obj.type})
- return JsonResponse({
- "result": 1,
- "description": None,
- "payload": {
- "sumCoins": sumCoins,
- 'sumCoinsTotal': sumCoinsTotal,
- 'sumCharge': sumCharge,
- 'sumChargeTotal': sumChargeTotal,
- "rcds": {
- "total": total,
- "items": rcdList[(pageIndex - 1) * pageSize:pageIndex * pageSize],
- }
- }
- })
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def handlerKeepingOrder(request):
- """
- 关闭订单取消订单
- 霍珀道闸 由于出现后付费的情况,可能存在两种情况需要将订单取消 用户扫码进门,创建了订单但是门没开 用户扫码出门,钱已经扣了但门没开
- 此接口 供经销商对于此类订单的处理
- """
- TYPE_CANCEL = "cancel"
- TYPE_CLOSE = "close"
- _id = request.GET.get("id")
- _type = request.GET.get("type")
- # 取消订单
- sp = ServiceProgress.objects.get(id=_id)
- sp.isFinished = True
- sp.finished_time = int(time.time())
- order = ConsumeRecord.objects.get(id=sp.consumes[0])
- if _type == TYPE_CLOSE:
- order.isNormal = True
- order.finishedTime = datetime.datetime.now()
- order.remarks = u"经销商 %s 关闭订单" % request.user.nickname
- serviceInfo = {
- "finishedTime": str(order.finishedTime)[:19],
- }
- order.serviceInfo = serviceInfo
- elif _type == TYPE_CANCEL:
- order.finishedTime = datetime.datetime.now()
- order.remarks = u"经销商 %s 取消订单" % request.user.nickname
- order.isNormal = False
- try:
- sp.save()
- order.save()
- except Exception as e:
- logger.exception(e)
- return JsonResponse({'result': 0, 'description': u'数据查询出错', 'payload': {}})
- else:
- # 清除该停车数量 无论是终止订单还是取消订单,其进车数量始终 需要 -1
- key = "maxParking"
- if order.attachParas.get("vCardId"):
- key = "VIPMaxParking"
- serviceInfo = HuopoCacheMgr.get_parking_cache(order.groupId)
- if serviceInfo is not None:
- parkingInfo = serviceInfo.get("parkingInfo", {})
- parkingNum = parkingInfo.get(key, 0)
- else:
- parkingInfo = {}
- parkingNum = 0
- if parkingNum > 0:
- parkingNum -= 1
- parkingInfo.update({key: parkingNum})
- HuopoCacheMgr.set_parking_cache(order.groupId, {"parkingInfo": parkingInfo})
- return JsonResponse({'result': 1, 'description': u'success'})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getKeepingOrder(request):
- """
- 获取正在进行的订单
- """
- pageIndex = int(request.GET.get("pageIndex", 1))
- pageSize = int(request.GET.get("pageSize", 10))
- ownerId = str(request.user.bossId)
- logicalCode = request.GET.get('logicalCode', None)
- attachParas = json.loads(request.POST.get('attachParas', '{}'))
- devNo = Device.get_devNo_by_logicalCode(logicalCode)
- dev = Device.get_dev(devNo)
- if not dev:
- return JsonResponse({'result': 0, 'description': u'设备不存在'})
- if dev['ownerId'] != ownerId:
- return JsonResponse({'result': 0, 'description': u'不是你家设备,不能操作喔'})
- sps = ServiceProgress.objects.filter(device_imei=devNo, devTypeCode=dev["devType"]["code"], isFinished=False).all()
- dataList = list()
- for sp in sps:
- user = MyUser.objects.filter(openId=sp.open_id).first()
- order = ConsumeRecord.objects.get(id=sp.consumes[0])
- tempData = {
- "id": sp.id,
- "nickname": user.nickname,
- "avatar": user.avatar,
- "startTime": order.time
- }
- dataList.append(tempData)
- return JsonResponse(
- {'result': 1,
- 'description': u'',
- 'payload':
- {
- "total": len(dataList),
- "dataList": dataList[(pageIndex-1)*pageSize: pageIndex*pageSize]
- }
- })
- # 获取默认地址
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def groupInfo(request):
- # 获取默认地址
- def groupInfoDefault(request):
- # type: (WSGIRequest)->JsonResponse
- groupId = request.GET.get('groupId', None)
- ownerId = str(request.user.bossId)
- group = Group.get_group(groupId)
- if group is None:
- return JsonResponse({"result": 0, "description": u"没有找到地址信息", "payload": {}})
- if group['ownerId'] == ownerId:
- group['isManager'] = True
- else:
- group['isManager'] = False
- groupOwner = Dealer.get_dealer(group['ownerId'])
- group['managerName'] = groupOwner['nickname'] + " " + groupOwner['username']
- group['partner'] = group['partnerDict'].values()
- for partner in group['partner']:
- if partner['id'] == ownerId:
- partner['self'] = True
- else:
- reload_parter = Dealer.get_dealer(partner['id'])
- partner['tel'] = reload_parter['username']
- partner['name'] = reload_parter['nickname']
- partner['self'] = False
- # 添加 合伙人商户的状态给前台显示 如果合伙人商户的状态是 初始状态 需要为合伙人绑定银行卡
- partner = Dealer.objects.get(id=partner["id"])
- district = District.get_district(group['districtId'])
- group['district'] = district
- if not group['isManager']:
- for i in range(len(group['partner'])-1,-1,-1):
- if not group['partner'][i]['self']:
- del group['partner'][i]
- return JsonResponse({"result": 1, "description": None, "payload": group})
- current_user = request.user # type: UserSearchable
- return groupInfoDefault(request)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def groupIncomeData(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 查询地址组的收益
- 地址组收益的记录方式已经发生了改变 对于收益的部分 记录在 daily.incomeMap下面的数据,每个经销商一条,为总的收益,没有明细划分
- :param request:
- :return:
- """
- def get_group_info(g, _id):
- isM = _id == g.get("ownerId")
- if not isM:
- p = round_2_digits(float(g.get("partnerDict", dict()).get(_id, dict()).get("percent", 0)))
- else:
- fullPercent = 100
- for _partner in g.get("partnerDict", dict()).values():
- fullPercent -= float(_partner.get("percent", 0))
- p = round_2_digits(float(fullPercent))
- return isM, p
- current_user = request.user # type: Dealer
- dealerId = str(current_user.bossId)
- pageIndex = int(request.GET.get("pageIndex", 1))
- pageSize = int(request.GET.get("pageSize", 10))
- startDate = request.GET.get("startTime")
- endDate = request.GET.get("endTime")
- startDate, endDate = current_user.limit_filter_date(startDate, endDate)
- if endDate < startDate:
- return JsonResponse({
- 'result': 1, 'description': '', 'payload': {
- "total": 0,
- "dataList": [],
- "adShow": current_user.adShow
- }})
- else:
- searchKey = request.GET.get("searchKey", None)
- # 通过searchKey 获取组地址 作为查询的筛选条件
- # TODO 这个地方有一个问题在于 如果 地址组的合伙人一旦修改 之前的合伙人无法看到历史的数据 而新的合伙人能看到之前的数据
- groupIds = Group.search_group_ids_of_dealer(
- dealerId, searchKey
- ) + Group.search_group_ids_of_partner(
- dealerId, searchKey
- )
- groupIdSlice = groupIds[(pageIndex - 1) * pageSize: pageSize * pageIndex]
- if not groupIdSlice:
- return JsonResponse({
- 'result': 1, 'description': '', 'payload': {
- "total": len(groupIds),
- "dataList": [],
- "adShow": current_user.adShow
- }})
- groupStatisticMap = GroupDailyStatsModelProxy.get_groups_income_statistic(groupIds=groupIdSlice, startDate=startDate, endDate=endDate, dealerId=dealerId)
- groupDevCountMap = Device.get_device_count_by_group(groupIdSlice)
- rptDict = GroupReport.get_rpt(groupIdSlice, startDate, endDate) # 投币的信息
- # 经销商的特性判断 的相关信息的获取
- dealer = Dealer.objects.get(id=dealerId)
- showOfflineCoin = True if 'show_offline_coins' in dealer.features else False
- # 整合数据
- dataList = list()
- for _groupId in groupIdSlice:
- # 统计信息的过滤
- groupStatistic = groupStatisticMap.get(_groupId, {})
- # 要提前将这个不存在的统计值pop出来
- dealerActualIncome = RMB(groupStatistic.pop("dealerActualIncome", 0))
- incomeList = translate_income(groupStatistic)
- totalIncome = sum_rmb(_['value'] for _ in incomeList)
- # 组信息 以及分成比例的计算
- group = Group.get_group(_groupId) or dict()
- isManager, percent = get_group_info(group, dealerId)
- value = {
- "groupName": group.get("groupName", ""),
- "groupId": _groupId,
- "address": group.get("address", ""),
- "equipmentCount": groupDevCountMap.get(_groupId, 0),
- "isManager": isManager,
- "percent": percent,
- "agentProfitShare": request.user.agentProfitShare,
- "offlineCoins": rptDict.get(_groupId, dict()).get('lineCoins', 0),
- "incomeList": incomeList,
- "totalIncome": totalIncome,
- "dealerActualIncome": dealerActualIncome
- }
- if not showOfflineCoin:
- value.pop('offlineCoins', None)
- dataList.append(value)
- # 对 totalIncome 排序 优先返回金额最多的地址组
- dataList = sorted(dataList, key=lambda x: float(x["totalIncome"]), reverse=True)
- total = len(groupIds)
- return JsonResponse({"result": 1, "description": None, "payload": {
- "total": total,
- "dataList": dataList,
- "adShow": current_user.adShow
- }})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getDevOffLineCoinStatByGroupId(request):
- # type: (WSGIRequest)->JsonResponse
- groupId = request.GET.get('groupId')
- group = Group.get_group(groupId)
- if not group:
- return JsonErrorResponse(u'找不到组ID')
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- startDate = defaultTodayDate(request.GET.get('startTime'))
- endDate = defaultTodayDate(request.GET.get('endTime'))
- total = Device.get_collection().find({'groupId': groupId}).count()
- devNoList = Device.get_devNos_by_group([groupId])
- devInfo = Device.get_dev_by_nos(devNoList)
- dataList = [
- {
- 'logicalCode': devInfo[devNo]['logicalCode'],
- 'groupNumber': devInfo[devNo]['groupNumber'],
- 'devTypeName': devInfo[devNo].get('devType', {}).get('name', ''),
- 'offlineCoins': rpt['lineCoins'],
- }
- for devNo, rpt in DevReport.get_rpt(devNoList, startDate, endDate).iteritems()
- ]
- return JsonResponse(
- {
- 'result': 1,
- 'description': '',
- 'payload':
- {
- 'total': total,
- 'groupName': group['groupName'],
- 'dataList': dataList[(pageIndex - 1) * pageSize:pageIndex * pageSize]
- }
- }
- )
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def groupIncomeByGroupId(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 获取 单一地址组的 收益 聚合信息
- :param request:
- :return:
- """
- dealerId = str(request.user.bossId)
- groupId = request.GET.get("groupId")
- startDate = request.GET.get("startTime")
- endDate = request.GET.get("endTime")
- if not groupId:
- return JsonErrorResponse(description=u'未提供地址ID')
- if groupId not in Group.get_group_ids_of_dealer_and_partner(dealerId):
- return JsonErrorResponse(description=u'无权限查看')
- group = Group.get_group(groupId)
- if not group:
- return JsonErrorResponse(description=u'组不存在')
- groupStatistic = GroupDailyStatsModelProxy.get_one_group_income_statistic(groupId, startDate, endDate)
- incomeTotalList = [{"name": u"总收益", "value": RMB(groupStatistic.get("totalIncome", 0))}]
- for _item in translate_income(groupStatistic):
- if _item.get("value", RMB(0)) > RMB(0):
- incomeTotalList.append(_item)
- return JsonResponse(
- {
- 'result': 1,
- 'description': 'ok',
- 'payload': {
- 'groupName': group['groupName'],
- "incomeTotalList": incomeTotalList
- }
- }
- )
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def groupConsumptionByGroupId(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 获取 单一地址组的 收益 聚合信息
- :param request:
- :return:
- """
- dealerId = str(request.user.bossId)
- groupId = request.GET.get("groupId")
- startDate = request.GET.get("startTime")
- endDate = request.GET.get("endTime")
- if not groupId:
- return JsonErrorResponse(description=u'未提供地址ID')
- if groupId not in Group.get_group_ids_of_dealer_and_partner(dealerId):
- return JsonErrorResponse(description=u'无权限查看')
- group = Group.get_group(groupId)
- if not group:
- return JsonErrorResponse(description=u'组不存在')
- groupStatistic = GroupDailyStatsModelProxy.get_one_group_consumption_statistic(groupId, startDate, endDate)
- agent = Agent.objects.get(id=request.user.agentId) # type: Agent
- consumptionTotalList = list()
- for _item in translate_consumption(groupStatistic, agent.hide_consume_kinds_dealer):
- if _item.get("value", Quantity(0)) > Quantity(0):
- consumptionTotalList.append(_item)
- return JsonResponse(
- {
- 'result': 1,
- 'description': 'ok',
- 'payload': {
- 'groupName': group['groupName'],
- "incomeTotalList": consumptionTotalList
- }
- }
- )
- EXTRA_INCOME_DEVICE_TYPE_CODES = [Const.DEVICE_TYPE_CODE_WASHCAR_LSHB]
- def realtime_income_available(typeCode):
- # type:(str)->bool
- return typeCode in EXTRA_INCOME_DEVICE_TYPE_CODES
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getRealtimeIncomeByDev(request):
- # type: (WSGIRequest)->JsonResponse
- # TODO 建立一个缓存的permission map 来将经销商ID与设备等相关权限对应起来
- logicalCode = request.GET.get('logicalCode')
- device = Device.get_dev_by_logicalCode(logicalCode)
- if not device:
- return JsonErrorResponse(description=u'设备不存在')
- typeCode = device['devType']['code']
- if realtime_income_available(typeCode):
- return JsonErrorResponse(description=u'不支持当前设备查询实时收入')
- translation = {
- 'cardFee': u'刷卡总额',
- 'coinFee': u'投币总额',
- 'mobileFee': u'支付总额'
- }
- if typeCode == Const.DEVICE_TYPE_CODE_CHARGING_SIJIANG:
- try:
- smartBox = ActionDeviceBuilder.create_action_device(device)
- conf = smartBox.get_dev_consume_count()
- return JsonResponse(
- {
- 'result': 1,
- 'description': '',
- 'payload':
- {
- 'realTimeIncome': [
- {'name': translation[k], 'value': v} for k, v in conf.iteritems() if k in translation
- ]
- }
- })
- except ServiceException as e:
- logger.debug('cannot get_extra_income_by_specific_devices device=%s' % (device,))
- logger.exception(e)
- return JsonErrorResponse(description=u'网络不畅通,请稍后再试')
- elif typeCode == Const.DEVICE_TYPE_CODE_WASHCAR_LSHB:
- try:
- # 获取设备上的卡的总收入、投币的总收入
- smartBox = ActionDeviceBuilder.create_action_device(device)
- mapping = {
- 'cardFee': smartBox.get_card_count(),
- 'coinFee': smartBox.get_coins_count()
- }
- return JsonResponse(
- {
- 'result': 1,
- 'description': '',
- 'payload': {
- 'realTimeIncome': [{'name': translation[k], 'value': v} for k, v in mapping.iteritems() if
- k in translation]
- }
- })
- except ServiceException as e:
- logger.debug('cannot get_extra_income_by_specific_devices device=%s' % (device,))
- logger.exception(e)
- return JsonErrorResponse(description=u'网络不畅通,请稍后再试')
- else:
- return JsonErrorResponse(description=u'不支持当前设备查询实时收入')
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def groupEquipmentIncomeByGroupId(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 获取组下设备按日期收益聚合数据
- :param request:
- :return:
- """
- # TODO Nicolas 此接口以及 groupEquipmentConsumptionByGroupId 存在问题
- # TODO Nicolas 当该地址下设备信息发生变更的时候 ,通过 GroupDaily 获取的信息 和通过 DeviceDaily 聚合获取的信息会不一致
- dealerId = str(request.user.bossId)
- groupId = request.GET.get("groupId", None)
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- startDate = request.GET.get('startTime')
- endDate = request.GET.get('endTime')
- if groupId is None:
- return JsonErrorResponse(description=u'未找到地址组,请重试')
- if groupId not in Group.get_group_ids_of_dealer_and_partner(dealerId):
- return JsonErrorResponse(description=u'无权限查看')
- group = Group.get_group(groupId)
- if not group:
- return JsonErrorResponse(description=u'组不存在')
- # 获取设备的日统计信息
- logicalCodes = Device.get_logicalCode_by_groupId(groupId)
- logicalCodeSlice = sorted(logicalCodes[(pageIndex - 1) * pageSize: pageIndex * pageSize])
- statisticMap = DeviceDailyStatsModelProxy.get_devices_income_statistic(logicalCodeSlice, startDate, endDate)
- dataList = list()
- for logicalCode in logicalCodeSlice:
- devStatistic = translate_income(statisticMap.get(logicalCode, dict()))
- devStatistic = [_statistic for _statistic in devStatistic if _statistic["value"] > RMB(0)]
- dev = Device.get_dev_by_l(logicalCode)
- dataList.append({
- "incomeList": devStatistic,
- "logicalCode": logicalCode,
- "groupId": groupId,
- "type": dev.get("devType", dict()).get("name"),
- 'groupNumber': dev.get('groupNumber'),
- 'realtimeIncomeAvailable': realtime_income_available(dev.get('devType', dict()).get('code'))
- })
- return JsonResponse(
- {
- 'result': 1,
- 'description': None,
- 'payload': {
- 'total': len(logicalCodes),
- 'dataList': dataList
- }
- }
- )
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def groupEquipmentConsumptionByGroupId(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 获取组下设备按日期消费聚合数据
- :param request:
- :return:
- """
- dealerId = str(request.user.bossId)
- groupId = request.GET.get("groupId", None)
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- startDate = request.GET.get('startTime')
- endDate = request.GET.get('endTime')
- if groupId is None:
- return JsonErrorResponse(description=u'未找到地址组,请重试')
- if groupId not in Group.get_group_ids_of_dealer_and_partner(dealerId):
- return JsonErrorResponse(description=u'无权限查看')
- group = Group.get_group(groupId)
- if not group:
- return JsonErrorResponse(description=u'组不存在')
- # 获取设备的日统计信息
- logicalCodes = Device.get_logicalCode_by_groupId(groupId)
- logicalCodeSlice = sorted(logicalCodes[(pageIndex-1)*pageSize: pageIndex*pageSize])
- statisticMap = DeviceDailyStatsModelProxy.get_devices_consumption_statistic(logicalCodeSlice, startDate, endDate)
- agent = Agent.objects.get(id = request.user.agentId) # type: Agent
- dataList = list()
- for logicalCode in logicalCodeSlice:
- devStatistic = translate_consumption(statisticMap.get(logicalCode, dict()), hides = agent.hide_consume_kinds_dealer)
- devStatistic = [_statistic for _statistic in devStatistic if _statistic["value"] > Quantity(0)]
- dev = Device.get_dev_by_l(logicalCode)
- dataList.append({
- "consumptionList": devStatistic,
- "logicalCode": logicalCode,
- "groupId": groupId,
- "type": dev.get("devType", dict()).get("name"),
- 'groupNumber': dev.get('groupNumber'),
- })
- return JsonResponse(
- {
- 'result': 1,
- 'description': "",
- 'payload': {
- 'total': len(logicalCodes),
- 'dataList': dataList
- }
- }
- )
- def get_income_by_cat(stat, date_range, field):
- return RMB(stat.get(date_range, {}).get('income', {}).get(field, 0))
- def get_daily_income_by_cat(stat, field):
- return get_income_by_cat(stat, 'daily', field)
- def get_monthly_income_by_cat(stat, field):
- return get_income_by_cat(stat, 'monthly', field)
- @permission_required(ROLE.dealer, ROLE.agent, ROLE.subaccount)
- def lastMonthIncome(request):
- """
- 按月统计 经销商的月收益
- 获取的数据是当月的收益数据累加的 以及 每天的收益累计总和
- :param request:
- :return:
- """
- dealerId = request.GET.get('dealerId') or str(request.user.bossId)
- timeStr = request.GET.get("time", datetime.date.today().strftime("%Y-%m"))
- startDate, endDate = get_start_and_end_by_month(monthStr = timeStr)
- rpts = {r['date']: r for r in DealerReport.get_rpts(dealerId, startDate, endDate)}
- # 获取每一天的数据 首先要对时间参数进行鉴别 如果是本月的话,那么最后一天就是今天
- dataList = list()
- totalIncome, payIncome, offlineCoins = RMB(0), RMB(0), VirtualCoin(0)
- rv = DealerDailyStatsModelProxy.get_days_income_stat(dealerId, timeStr)
- for day, stat in rv.iteritems():
- day_offline_count = VirtualCoin(rpts.get(day, {}).get('lineCoins', 0))
- offlineCoins += day_offline_count
- day_pay_income = RMB(get_in(["income", format(DEALER_INCOME_SOURCE.RECHARGE)], stat, default = 0)) + \
- RMB(get_in(["income", format(DEALER_INCOME_SOURCE.REDPACK)], stat, default = 0)) + \
- RMB(get_in(["income", format(DEALER_INCOME_SOURCE.RECHARGE_CARD)], stat, default = 0)) + \
- RMB(get_in(["income", format(DEALER_INCOME_SOURCE.RECHARGE_VIRTUAL_CARD)], stat, default = 0)) + \
- RMB(get_in(["income", format(DEALER_INCOME_SOURCE.REFUND_CASH)], stat, default = 0))
- payIncome += day_pay_income
- day_total_income = RMB(get_in(["totalIncome"], stat, default = 0))
- totalIncome += day_total_income
- dataList.append({
- 'dateStr': day,
- 'dateText': u'%s年%s月%s日' % tuple(day.split('-')),
- 'payIncome': day_pay_income,
- 'offlineCoins': day_offline_count,
- 'totalIncome': day_total_income
- })
- if dealerId == '5d132407003048494763a51b':
- if int(timeStr[0:4]) < 2021:
- dataList = []
- offlineCoins = 0
- payIncome = 0
- totalIncome = 0
- else:
- pass
- return JsonOkResponse(payload=
- {
- "adShow": request.user.adShow,
- "totalIncome": totalIncome,
- "payIncome": payIncome,
- "offlineCoins": offlineCoins,
- "dataList": dataList
- })
- @permission_required(ROLE.dealer, ROLE.agent, ROLE.subaccount)
- def lastYearIncome(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 按年统计经销商的收益
- :param request:
- :return:
- """
- dealerId = request.GET.get('dealerId') or str(request.user.bossId)
- timeStr = request.GET.get("time", datetime.date.today().strftime("%Y"))
- timeStr = Dealer.limit_filter_year(dealerId, timeStr[0:4])
- if not timeStr:
- return JsonOkResponse(payload = {'adShow': request.user.adShow, 'dataList': []})
- else:
- startDay, endDay = get_start_and_end_by_year(timeStr)
- monthRange = [datetime.datetime.strftime(item, "%Y-%m") for item in get_date_range(startDay, endDay, "MS")]
- offline_report = DealerReportModelProxy.get_year_by_month(dealerId = dealerId, yearStr = timeStr)
- # 获取一年里面 按月聚合分组的数据
- statisticMap = DealerDailyStatsModelProxy.get_one_year_income_as_month(dealerId = dealerId, yearStr = timeStr)
- dataList = list()
- for month in monthRange:
- monthIncomeMap = statisticMap.get(month, dict())
- tempMonthStatistics = {
- "totalIncome": RMB(monthIncomeMap.get("totalIncome", 0)),
- "offlineCoins": VirtualCoin(
- offline_report.get('%d-%02d' % tuple(map(int, month.split('-'))), {}).get('lineCoins', 0)),
- "dateStr": month,
- "dateText": u"{}年{}月".format(*month.split("-")),
- "payIncome": sum([_v for _k, _v in monthIncomeMap.items() if
- _k in [DEALER_INCOME_SOURCE.RECHARGE_VIRTUAL_CARD,
- DEALER_INCOME_SOURCE.RECHARGE_CARD,
- DEALER_INCOME_SOURCE.RECHARGE,
- DEALER_INCOME_SOURCE.REFUND_CASH,
- DEALER_INCOME_SOURCE.REDPACK]], RMB(0))
- }
- dataList.append(tempMonthStatistics)
- return JsonOkResponse(payload = {'adShow': request.user.adShow, 'dataList': dataList})
- @permission_required(ROLE.dealer, ROLE.agent, ROLE.subaccount)
- def lastMonthConsumption(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 按月统计 经销商的消耗信息
- :param request:
- :return:
- """
- dealerId = request.GET.get('dealerId') or str(request.user.bossId)
- dealer = Dealer.objects.get(id=dealerId)
- timeStr = request.GET.get("time", datetime.date.today().strftime("%Y-%m"))
- _year = Dealer.limit_filter_year(dealerId, timeStr[0:4])
- if not _year:
- return JsonOkResponse(payload = {'dataList': []})
- else:
- agent = Agent.objects.get(id = request.user.agentId)
- dataList = list()
- rv = DealerDailyStatsModelProxy.get_days_consume_stat(dealerId, timeStr)
- for _day, stat in rv.iteritems():
- consumptionList = translate_consumption(get_in(["consumption"], stat, dict()),
- hides = agent.hide_consume_kinds_dealer)
- if "not_show_about_elec" in dealer.features:
- [consumptionList.pop(consumptionList.index(_c)) for _c in consumptionList if _c.get("name") == u"消耗电量"]
- [consumptionList.pop(consumptionList.index(_c)) for _c in consumptionList if _c.get("name") == u"电费成本"]
- dataList.append({
- "dateStr": _day,
- "dateText": u"{}年{}月{}日".format(*_day.split("-")),
- "consumptionList": consumptionList
- })
- return JsonOkResponse(payload = {'dataList': dataList})
- @permission_required(ROLE.dealer, ROLE.agent, ROLE.subaccount)
- def lastYearConsumption(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 一年的消费概览
- :param request:
- :return:
- """
- dealerId = request.GET.get('dealerId') or str(request.user.bossId)
- timeStr = request.GET.get("time", datetime.date.today().strftime("%Y"))
- timeStr = Dealer.limit_filter_year(dealerId, timeStr)
- if not timeStr:
- return JsonOkResponse(payload = {'dataList': []})
- else:
- # 获取统计的时间范围 获取月份的区间
- startDay, endDay = get_start_and_end_by_year(timeStr)
- monthRange = [datetime.datetime.strftime(item, "%Y-%m") for item in get_date_range(startDay, endDay, "MS")]
- # 获取一年里面 按月聚合分组的消费数据
- statisticMap = DealerDailyStatsModelProxy.get_one_year_consume_as_month(dealerId = dealerId, yearStr = timeStr)
- # 消费信息 某些字段和特性相关联 先取出代理商的特性 留作判断
- agent = Agent.objects.get(id = request.user.agentId)
- dataList = list()
- for _month in monthRange:
- _item = statisticMap.get(_month, dict())
- consumptionList = translate_consumption(_item, hides=agent.hide_consume_kinds_dealer)
- dataList.append({
- "dateStr": _month,
- "dateText": u"{}年{}月".format(*_month.split("-")),
- "consumptionList": consumptionList
- })
- return JsonOkResponse(payload={'dataList': dataList})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def updateInfo(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 支持经销商更改用户信息
- :param request:
- :return:
- """
- name = request.POST.get('name', '')
- if NAME_RE.match(name) is None:
- logger.info('update dealer name doesn\'t fit format, name=%s' % (name.encode('utf-8'),))
- return JsonResponse({"result": 0, "description": "请输入正确格式的名称(2-20位)"})
- if check_role(request.user, ROLE.dealer):
- dealer = Dealer.objects(id=request.user.bossId).first() # type: Union[Dealer,None]
- if dealer is None:
- return JsonResponse({"result": 0, "description": "该经销商不存在"})
- updated = dealer.update_dealer(ownerId=str(dealer.id), nickname=name)
- if not updated:
- logger.info('Dealer [updateInfo] failed, name=%s' % (name.encode('utf-8'),))
- return JsonResponse({"result": 0, "description": u'更新失败,请重试'})
- else:
- return JsonResponse({"result": 1, "description": None})
- else:
- subaccount = SubAccount.objects(id=request.user.id).first() # type: Union[Dealer,None]
- if subaccount is None:
- return JsonResponse({"result": 0, "description": "该经销商不存在"})
- updated = subaccount.update(nickname=name)
- if not updated:
- logger.info('subaccount [updateInfo] failed, name=%s' % (name.encode('utf-8'),))
- return JsonResponse({"result": 0, "description": u'更新失败,请重试'})
- else:
- return JsonResponse({"result": 1, "description": None})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def verifyNewPhoneNumber(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 修改经销商手机号
- :param request:
- :return:
- """
- code = request.POST.get('code')
- if not code:
- return JsonResponse({"result": 0, "description": u'请输入验证码'})
- phoneNumber = request.POST.get('phone')
- if PHONE_NUMBER_RE.match(phoneNumber) is None:
- logger.info('phone number format error, phone=%s' % phoneNumber)
- return JsonResponse({"result": 0, "description": u"请输入正确的手机号码"})
- if check_role(request.user, ROLE.dealer):
- dealer = Dealer.objects(id=request.user.bossId).first() # type: Optional[Dealer]
- if dealer is None:
- return JsonResponse({"result": 0, "description": u"该经销商不存在"})
- # : 检测是否系统内已有该号码,为了防止混淆
- if Dealer.objects(username=phoneNumber).first():
- return JsonResponse({"result": 0, "description": u"已存在与该手机号码绑定的账户"})
- status, msg = dealerRegisterSMSProvider.verify(phoneNumber, code)
- if status:
- updated = dealer.update_dealer(ownerId=str(dealer.id), username=phoneNumber)
- if updated:
- Dealer.invalid_cache(dealer.id)
- return JsonResponse({"result": 1, "description": None})
- else:
- return JsonResponse({"result": 0, "description": u'更换失败'})
- else:
- return JsonResponse({"result": 0, "description": msg})
- else:
- subAccount = SubAccount.objects(id=request.user.id,
- agentId=request.user.agentId).first() # type: Optional[Dealer]
- if subAccount is None:
- return JsonResponse({"result": 0, "description": u"该子账号不存在"})
- # : 检测是否系统内已有该号码,为了防止混淆
- if SubAccount.objects(username=phoneNumber, agentId=request.user.agentId).first():
- return JsonResponse({"result": 0, "description": u"已存在与该手机号码绑定的子账户"})
- status, msg = dealerRegisterSMSProvider.verify(phoneNumber, code)
- if status:
- updated = subAccount.update(username=phoneNumber)
- if updated:
- return JsonResponse({"result": 1, "description": None})
- else:
- return JsonResponse({"result": 0, "description": u'更换失败'})
- else:
- return JsonResponse({"result": 0, "description": msg})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def setAddressFree(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 设置部分地址为免费地址, 其同一地址下所有设备都会供免费使用
- :param request:
- :return:
- """
- payload = parse_json_payload(request.body)
- groupId = payload.get('groupId', None)
- isFree = payload.get('isFree', False)
- currentDealer = request.user.myBoss # type: Optional[Dealer]
- if currentDealer.get_feature('disable_set_group_free').get('disable_set_group_free', False):
- return JsonResponse(
- {'result': 0, 'description': '设备无法使用该功能奥, 如有问题, 请联系代理商', 'payload': {}})
- if groupId is None:
- return JsonResponse({"result": 0, "description": u'地址不可为空'})
- try:
- Group.update_group(group_id=groupId, isFree=isFree)
- return JsonResponse({"result": 1, "description": None})
- except Exception as e:
- logger.exception(e)
- return JsonResponse({"result": 0, "description": u'修改失败'})
- #### `经销商报表版块` ###############################################################
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def dateCoins(request):
- """
- TODO 线下投币相关数据与收益计算展现彻底分离,接口需要重新审视
- :param request:
- :return:
- """
- ownerId = str(request.user.bossId)
- now = datetime.datetime.now()
- rpt = Accounting.getOwnerIncome(ownerId, now)
- return JsonResponse({"result": 1, "description": None, 'payload': {"coins": rpt["lineCoins"]}})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def dateCoinsDetail(request):
- """
- TODO 线下投币相关数据与收益计算展现彻底分离,接口需要重新审视
- :param request:
- :return:
- """
- ownerId = str(request.user.bossId)
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- nowDate = datetime.datetime.now().strftime('%Y-%m-%d')
- groupIds = Group.get_group_ids_of_dealer(ownerId)
- devNos = Device.get_devNos_by_group(groupIds)
- keys = [devCoinTmpl(devNo, nowDate) for devNo in devNos]
- devCoinDict = reportCache.get_many(keys)
- devNoList = []
- for key, coins in devCoinDict.items():
- coins = int(coins)
- if coins == 0:
- continue
- tempList = key.split('_')
- devNo = tempList[1]
- devNoList.append({'devNo': devNo, 'coins_count': coins})
- sorted(devNoList, key=lambda dev: dev['coins_count'], reverse=True)
- total = len(devNoList)
- resultDevDictList = devNoList[(pageIndex - 1) * pageSize:pageIndex * pageSize]
- devNoList = [dev['devNo'] for dev in resultDevDictList]
- devDict = Device.get_dev_by_nos(devNoList)
- groupIds = [dev['groupId'] for dev in devDict.values()]
- groupDict = Group.get_groups_by_group_ids(groupIds)
- dataList = []
- for dev in resultDevDictList:
- if dev['devNo'] not in devDict:
- logger.warning('dev<IMEI={}> not belong to dealer<id={}>'.format(dev['devNo'], ownerId))
- continue
- devDetail = devDict[dev['devNo']]
- groupDetail = groupDict[devDetail['groupId']]
- dataList.append({
- 'value': devDetail['logicalCode'],
- 'coins_count': dev['coins_count'],
- "online": devDetail["online"],
- "remark": devDetail["remarks"],
- "type": devDetail['devType']['name'],
- "groupNumber": devDetail["groupNumber"],
- "groupName": groupDetail['groupName'],
- "status": devDetail['status'],
- "statusInfo": devDetail['statusInfo']
- })
- return JsonResponse({"result": 1, "description": None, 'payload': {"total": total, "dataList": dataList}})
- ########################
- #### 经销商收益消费数据中心
- ########################
- @require_GET
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取收益统计失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getIncomeStatistics(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 经销商经营统计 首页获取入口
- :param request:
- :return:
- """
- currentDealer = request.user # type: cast(Dealer)
- groupIds = Group.get_group_ids_of_dealer_and_partner(str(currentDealer.bossId))
- stats = [
- {
- "name": u"完成订单",
- "value": GroupDailyStat.get_today_recharge_count(groupIds=groupIds),
- "effect": "good",
- "unit": "",
- "necessary": True
- }
- ]
- agent = Agent.objects(id=currentDealer.agentId).get() # type: Agent
- start, end = today_datetime_range()
- if not agent.supports('hide_dealer_newly_user_added_count'):
- stats.append({
- "name": u"新增用户",
- "value": MyUser.get_new_user_count(groupIds=groupIds, start=start, end=end),
- "effect": "good",
- "unit": "",
- "necessary": True
- })
- dailyStat = DealerDailyStat.get_today(currentDealer.bossId)
- consumption = dailyStat.get("consumption", dict())
- for kind in agent.hide_consume_kinds_dealer:
- consumption.pop(kind, None)
- for kind, value in consumption.iteritems():
- stats.append(
- {
- "source": kind,
- "name": DEALER_CONSUMPTION_AGG_KIND_TRANSLATION.get(kind, ''),
- "value": to_quantity(kind, value),
- "effect": "good",
- "unit": DEALER_CONSUMPTION_AGG_KIND_UNIT.get(kind, ''),
- "necessary": False
- }
- )
- # 将非必须的并且值为 0的过滤掉
- todayStatList = filter(lambda _: float(str((_.get("value", 0)))) > 0 or _.get("necessary"), stats)
- now = datetime.datetime.now()
- monthStr = MONTH_DATE_KEY.format(year=now.year, month=now.month)
- return JsonOkResponse(
- payload={
- "monthIncome": DealerDailyStatsModelProxy.get_one_month_income(
- dealerId = currentDealer.bossId, monthStr = monthStr),
- "todayIncome": DealerDailyStat.get_today_income(dealerId = currentDealer.bossId),
- 'todayRefundCash': abs(DealerDailyStat.get_today_refund_cash(dealerId = currentDealer.bossId)),
- "todayStatList": todayStatList
- }
- )
- @require_GET
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取收益消费来源失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getIncomeConsumptionCategories(request):
- # type: (WSGIRequest)->JsonResponse
- """
- :param request:
- :return:
- """
- currentDealer = request.user # type: cast(Dealer)
- expand = lambda _: [{'text': v, 'value': k} for k, v in _.items()]
- return JsonResponse(
- {
- 'result': 1,
- 'description': '',
- 'payload': {
- 'income': expand(currentDealer.income_aggregate_source),
- 'consumption': expand(currentDealer.consumption_aggregate_source)
- }
- })
- @require_GET
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取收益列表失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getIncomeList(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 经销商经营统计的列表 从incomeProxy维度读取
- :param request:
- :return:
- """
- current_dealer = request.user # type: Union[Dealer, SubAccount]
- current_dealer_id = str(current_dealer.bossId)
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- startTime = request.GET.get("startTime")
- endTime = request.GET.get("endTime")
- logicalCode = request.GET.get("logicalCode")
- source = request.GET.get("secondary")
- groupId = request.GET.get('groupId')
- if groupId and groupId == 'undefined':
- return JsonErrorResponse(description=u'地址过滤参数错误,请刷新后重试')
- if not groupId:
- groupIds = [ObjectId(groupId) for groupId in Group.get_group_ids_of_dealer_and_partner(current_dealer_id)]
- else:
- groupIds = [ObjectId(groupId)]
- searchKey = request.GET.get("searchKey")
- filters = {
- "groupId__in": groupIds,
- }
- if logicalCode:
- filters.update({"logicalCode": logicalCode})
- # 将source为 保险的排除 经销商的主营收益仅仅为以下几种
- if source:
- sources = [source]
- else:
- sources = [
- DEALER_INCOME_SOURCE.REFUND_CASH,
- DEALER_INCOME_SOURCE.RECHARGE,
- DEALER_INCOME_SOURCE.REDPACK,
- DEALER_INCOME_SOURCE.OFFLINE_COIN,
- DEALER_INCOME_SOURCE.LEDGER_CONSUME,
- ]
- filters.update({"source__in": sources})
- if searchKey:
- filters.update({"searchKey": searchKey})
- startTime, endTime = current_dealer.limit_filter_date(startTime, endTime)
- if startTime > endTime:
- return JsonResponse({
- 'result': 1,
- 'description': None,
- 'payload': {
- 'total': 0,
- 'adShow': current_dealer.adShow,
- 'totalAmount': RMB(0),
- 'dataList': [],
- }
- })
- # 获取收益集合
- st = datetime.datetime.strptime(startTime, "%Y-%m-%d")
- et = datetime.datetime.strptime(endTime, "%Y-%m-%d")
- incomeQuery = DealerIncomeProxy.objects.filter(dateTimeAdded__gte=st, dateTimeAdded__lt=et+datetime.timedelta(days=1), **filters) # type: CustomQuerySet
- total, totalAmount = incomeQuery.sum_and_count("actualAmountMap.{}".format(current_dealer_id))
- # 第一次循环提取出收益模型以及其对应的充值单号
- incomes = list()
- ref_ids = list()
- for _income in incomeQuery.paginate(pageIndex, pageSize): # type: DealerIncomeProxy
- incomes.append(_income)
- ref_ids.append(_income.ref_id)
- # 最后看是否需要执行内存合单
- dataList = list()
- for _record in incomes:
- _data = _record.to_dict(dealerId=current_dealer_id)
- dataList.append(_data)
- return JsonResponse(
- {
- 'result': 1,
- 'description': "",
- 'payload': {
- 'total': total,
- 'adShow': current_dealer.adShow,
- 'totalAmount': RMB(totalAmount),
- 'dataList': dataList,
- }
- }
- )
- @require_GET
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取收益详情失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getIncomeDetail(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 根据 存在收入代理里的`ref_id`来获取真实的收入对应的对象,以拼装出真实的详情
- :param request:
- :return:
- """
- currentDealerId = str(request.user.bossId)
- _id = request.GET.get("id")
- _ref_id = request.GET.get("ref_id")
- if not any([_id, _ref_id]) or 'groupId' not in request.GET:
- return JsonErrorResponse(description=u'参数错误,请刷新后再试')
- filters = {"id": _id} if _id else {"ref_id": ObjectId(_ref_id)}
- filters.update({'shard_filter': {'groupId': request.GET.get('groupId')}})
- record = ClientDealerIncomeModelProxy.get_one(**filters) # type: DealerIncomeProxy
- if not record:
- return JsonErrorResponse(description=u"未查询到该笔订单")
- data = record.ref_detail(currentDealerId)
- startKey = data.get("startKey", None)
- if startKey:
- consumeRecord = ConsumeRecord.objects(startKey=data.get('startKey', '')).first()
- if consumeRecord is not None:
- data.update({'orderNo': consumeRecord.orderNo})
- data.update({'consumeId': str(consumeRecord.id)})
- rechargeRecord = RechargeRecord.objects.filter(id=record.ref_id).first()
- if rechargeRecord is not None and rechargeRecord.via == 'redpack':
- data.update({'gateway': 'redpack'})
- # 新加入一个判断,如果是group owner则显示全部正常信息,如果不是只显示全部金额和自己分到的金额信息
- # 判断是否是group owner,如果是group显示全部完整信息
- for partnerInfo in data['incomePartitionList']:
- if partnerInfo['owner']:
- if partnerInfo['role'] == 'me':
- return JsonResponse({'result': 1, 'description': '', 'payload': data})
- # 判断是role是否是me,如果不是本人信息则不显示
- for i in range(len(data['incomePartitionList']) - 1, -1, -1):
- if data['incomePartitionList'][i]['role'] != 'me':
- del data['incomePartitionList'][i]
- return JsonResponse({'result': 1, 'description': '', 'payload': data})
- @require_GET
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取消费列表失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getConsumptionList(request):
- # type: (WSGIRequest)->JsonResponse
- """
- :param request:
- :return:
- """
- def coin_quantity(amount):
- # type:(float)->Quantity
- return Quantity(amount, places=consumption_unit_precision(DEALER_CONSUMPTION_AGG_KIND.COIN))
- current_dealer = request.user # type: cast(Dealer)
- current_dealer_id = str(current_dealer.bossId)
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- startTime = request.GET.get('startTime')
- endTime = request.GET.get('endTime')
- startTime, endTime = current_dealer.limit_filter_date(startTime, endTime)
- if endTime < startTime:
- return JsonResponse({
- 'result': 1,
- 'description': None,
- 'payload': {
- 'total': 0,
- 'adShow': current_dealer.adShow,
- 'totalAmount': RMB(0),
- 'dataList': []
- }
- })
- else:
- logicalCode = request.GET.get("logicalCode")
- source = request.GET.get("secondary")
- groupId = request.GET.get('groupId')
- filters = {
- "status__in": [
- ConsumeRecord.Status.FINISHED,
- ConsumeRecord.Status.END,
- ConsumeRecord.Status.TIMEOUT,
- ConsumeRecord.Status.WAIT_PAY,
- ConsumeRecord.Status.CREATED,
- ]
- }
- if not groupId:
- filters.update({
- 'ownerId__in': Dealer.get_cooperative_dealer_ids(current_dealer_id),
- 'groupId__in': Dealer.get_cooperative_group_ids(current_dealer_id)
- })
- else:
- group = Group.get_group(groupId) # type: GroupDict
- filters.update({
- 'shard_filter': {'ownerId': group.ownerId},
- 'groupId': groupId
- })
- searchKey = request.GET.get("searchKey")
- if logicalCode:
- filters.update({
- "logicalCode": logicalCode
- })
- if source:
- filters.update({"aggInfo__{}__exists".format(source): True})
- if searchKey:
- filters.update({"searchKey": searchKey})
- # 获取的是总的数据条目
- records = ConsumeRecord.objects.filter(
- dateTimeAdded__gte=to_datetime(startTime, "%Y-%m-%d"),
- dateTimeAdded__lt=to_datetime(endTime, "%Y-%m-%d")+datetime.timedelta(days=1),
- **filters
- )
- total, totalAmount = records.sum_and_count("coin")
- totalAmount = coin_quantity(totalAmount)
- return JsonResponse(
- {
- 'result': 1,
- 'description': None,
- 'payload':
- {
- 'total': total,
- 'adShow': current_dealer.adShow,
- 'totalAmount': totalAmount,
- 'dataList': [
- _record.to_dealer_list() for _record in
- records.paginate(pageIndex, pageSize)
- ],
- }
- })
- @require_GET
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取消费详情失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getConsumptionDetail(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 消费详情应该附上成本信息(如果有)
- 通过RECHARGE查询CONSUME有两种情况. 一个是CONSUME一定在RECHARGE之后; 还有一个是
- 后支付, RECHARGE后建立起来. 这种情况下会在RECHARGE保存consumeid
- :param request:
- :return:
- """
- id_ = request.GET.get('id')
- start_key = request.GET.get('startKey')
- filters = {'shard_filter': {"ownerId": request.GET.get('ownerId')}}
- if id_:
- filters.update({"id": str(id_)})
- record = ClientConsumeModelProxy.get_one(**filters) # type: ConsumeRecord
- elif start_key:
- filters.update({"startKey": start_key, "hint": [("startKey", 1)]})
- record = ClientConsumeModelProxy.get_one(foreign_id=request.GET.get('ref_id'),
- **filters) # type: ConsumeRecord
- else:
- logger.error("[getConsumptionDetail] not id and not startKey !")
- return JsonErrorResponse(description=u'参数错误,请刷新后再试')
- payload = record.to_detail()
- if payload.has_key('aggInfo'):
- newAggInfo = [remove_some_desc_for_consume(value, u'使用时长') for value in payload['aggInfo']]
- payload['aggInfo'] = newAggInfo
- if record.isNormal:
- device = Device.get_dev(record.devNo) # type: DeviceDict
- if device:
- payload.update({
- 'showPG': device.support_power_graph
- })
- else:
- payload.update({'showPG': False})
- return JsonOkResponse(payload=payload)
- @require_POST
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"关闭订单失败"))
- @permission_required(ROLE.dealer)
- def closeOrder(request):
- payload = json.loads(request.body)
- orderId = payload.get("orderId", "")
- order = ClientConsumeModelProxy.get_one(id=orderId)
- order.status = "finished"
- order.save()
- return JsonOkResponse()
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def groupConsumptionData(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 经销商旗下所有组的消费数据
- :param request:
- :return:
- """
- def get_group_info(g, _id):
- isM = _id == g.get("ownerId")
- if not isM:
- p = round_2_digits(float(g.get("partnerDict", dict()).get(_id, dict()).get("percent", 0)))
- else:
- fullPercent = 100
- for _partner in g.get("partnerDict", dict()).values():
- fullPercent -= float(_partner.get("percent", 0))
- p = round_2_digits(float(fullPercent))
- return isM, p
- current_user = request.user # type: Dealer
- dealerId = str(current_user.bossId)
- dealer = Dealer.objects.get(id=dealerId)
- pageIndex = int(request.GET.get("pageIndex", 1))
- pageSize = int(request.GET.get("pageSize", 10))
- startDate = request.GET.get("startTime")
- endDate = request.GET.get("endTime")
- startDate, endDate = current_user.limit_filter_date(startDate, endDate)
- if endDate < startDate:
- return JsonResponse({
- 'result': 1,
- 'description': '',
- 'payload': {
- 'dataList': [],
- 'total': 0,
- 'adShow': current_user.adShow
- }
- })
- else:
- searchKey = request.GET.get("searchKey", None)
- # 通过searchKey 获取组地址 作为查询的筛选条件
- groupIds = Group.search_group_ids_of_dealer(dealerId, searchKey) + \
- Group.search_group_ids_of_partner(dealerId, searchKey)
- # 每个地址组一个单位 ,根据地址组ID来完成对数据分页
- groupIdSlice = groupIds[(pageIndex - 1) * pageSize: pageSize * pageIndex]
- groupStatisticMap = GroupDailyStatsModelProxy.get_groups_consumption_statistic(groupIds=groupIdSlice,
- startDate=startDate,
- endDate=endDate)
- groupDevCountMap = Device.get_device_count_by_group(groupIdSlice)
- agent = Agent.objects.get(id=current_user.agentId)
- isHiddenUsedTime = True if 'hiddenUsedTime' in agent.features else False
- dataList = list()
- for _groupId in groupIdSlice:
- groupStatistic = groupStatisticMap.get(_groupId, dict())
- consumptionList = translate_consumption(groupStatistic, hides=agent.hide_consume_kinds_dealer)
- # 志高电子隐藏经销商后台消耗电量和电费成本统计
- if "not_show_about_elec" in dealer.features:
- [consumptionList.pop(consumptionList.index(_c)) for _c in consumptionList if _c.get("name") == u"消耗电量"]
- [consumptionList.pop(consumptionList.index(_c)) for _c in consumptionList if _c.get("name") == u"电费成本"]
- if isHiddenUsedTime:
- consumptionList = [_c for _c in consumptionList if _c.get("name") != u"使用时长"]
- group = Group.get_group(_groupId)
- isManager, percent = get_group_info(group, dealerId)
- dataList.append({
- 'groupName': group['groupName'],
- 'groupId': group['groupId'],
- 'address': group['address'],
- 'equipmentCount': groupDevCountMap.get(_groupId, 0),
- 'agentProfitShare': request.user.agentProfitShare,
- 'isManager': group.get("ownerId") == dealerId,
- 'consumptionList': consumptionList
- })
- dataList = sorted(dataList, key=lambda x: float(x['equipmentCount']), reverse=True)
- total = len(groupIds)
- return JsonResponse({
- 'result': 1,
- 'description': '',
- 'payload': {
- 'dataList': dataList,
- 'total': total,
- 'adShow': request.user.adShow
- }
- })
- ##################################################################################
- #### `经销商信息设置` ###############################################################
- ##################################################################################
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'更新失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def resetPassword(request):
- # type: (WSGIRequest)->JsonResponse
- dealer = request.user
- oldPassword = request.POST.get('oldPassword', "")
- if not oldPassword:
- return JsonErrorResponse(description=u"请输入旧密码")
- limitManager = LimitAttemptsManager('resetPassword', oldPassword)
- if limitManager.is_exceeded_limit():
- return JsonErrorResponse(description=u'超出输入错误次数限制,请明日再试')
- if dealer.check_password(oldPassword):
- password = request.POST.get('password', "")
- if password == "":
- return JsonErrorResponse(description=u"请输入密码")
- else:
- dealer.set_password(password)
- request.session['password'] = password
- limitManager.clear()
- return JsonOkResponse()
- else:
- limitManager.incr()
- return JsonErrorResponse(description=u'旧密码输入错误,您还可输入%s次' % limitManager.times_left())
- # : 开关
- # : 可考虑以后整合成一个接口
- # : @url('service/toggleSwitches')
- # : def f(request):
- # : dealer.update(**json.loads(request.body))
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'更新错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def setWithdrawMsgSwitch(request):
- # type: (WSGIRequest)->JsonResponse
- ownerId = str(request.user.bossId)
- payload = json.loads(request.body) if request.body else {}
- if not payload:
- return JsonResponse({"result": 0, "description": u'数据不完整, 更新失败', 'payload': {}})
- if payload['on'] and (not request.user.isManagerialOpenIdBound):
- return JsonResponse({"result":-1, "description": u"请先绑定微信号接收消息"})
- updated = Dealer.objects(id=ownerId).update(withdrawlNotify=payload.get('on', False))
- if updated:
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- else:
- return JsonResponse({"result": 0, "description": u'更新失败', 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'更新错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def setOfflineNotifySwitch(request):
- # type: (WSGIRequest)->JsonResponse
- """
- :param request:
- :return:
- """
- ownerId = str(request.user.bossId)
- payload = json.loads(request.body) if request.body else {}
- if not payload:
- return JsonResponse({"result": 0, "description": u'数据不完整, 更新失败', 'payload': {}})
- if payload['on'] and (not request.user.isManagerialOpenIdBound):
- return JsonResponse({"result":-1, "description": u"请先绑定微信号接收消息"})
- updated = Dealer.objects(id=ownerId).update(offlineNotifySwitch=payload.get('on', False))
- if updated:
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- else:
- return JsonResponse({"result": 0, "description": u'更新失败', 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'更新错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def saveOfflineNotifyTime(request):
- # type: (WSGIRequest)->JsonResponse
- """
- :param request:
- :return:
- """
- ownerId = str(request.user.bossId)
- payload = json.loads(request.body) if request.body else {}
- if not payload:
- return JsonResponse({"result": 0, "description": u'数据不完整, 更新失败', 'payload': {}})
- if payload['offlineNotifyTime'] and (not request.user.isManagerialOpenIdBound):
- return JsonResponse({"result":-1, "description": u"请先绑定微信号接收消息"})
- updated = Dealer.objects(id=ownerId).update(offlineNotifyTime=str(payload.get('offlineNotifyTime', '')))
- if updated:
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- else:
- return JsonResponse({"result": 0, "description": u'更新失败', 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'更新错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def toggleNewUserPaymentOrderPushSwitch(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 用户支付订单后,即时推送给经销商
- :param request:
- :return:
- """
- ownerId = str(request.user.bossId)
- payload = json.loads(request.body) if request.body else {}
- if not payload:
- return JsonResponse({"result": 0, "description": u'数据不完整, 更新失败', 'payload': {}})
- if payload['on'] and (not request.user.isManagerialOpenIdBound):
- return JsonResponse({"result":-1, "description": u"请先绑定微信号接收消息"})
- updated = Dealer.objects(id=ownerId).update(newUserPaymentOrderPushSwitch=payload.get('on', False))
- if updated:
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- else:
- return JsonResponse({"result": 0, "description": u'更新写入失败', 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'更新错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def toggleDailyIncomeReportPushSwitch(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 每日9点推送昨日报表
- :param request:
- :return:
- """
- ownerId = str(request.user.bossId)
- payload = json.loads(request.body) if request.body else {}
- if not payload:
- return JsonResponse({"result": 0, "description": u'数据不完整, 更新失败', 'payload': {}})
- if payload['on'] and (not request.user.isManagerialOpenIdBound):
- return JsonResponse({"result":-1, "description": u"请先绑定微信号接收消息"})
- updated = Dealer.objects(id=ownerId).update(dailyIncomeReportPushSwitch=payload.get('on', False))
- if updated:
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- else:
- return JsonResponse({"result": 0, "description": u'更新失败', 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'查询错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def paymentOrderRecords(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 经销商后台查询充值订单(仅仅查询充值订单的 退币一些列的不要展示了)
- :param request:
- :return:
- """
- ownerId = str(request.user.bossId)
- payload = json.loads(request.body)
- pageIndex = payload.get("pageIndex")
- pageSize = payload.get("pageSize")
- startTime = payload.get("startTime")
- endTime = payload.get("endTime")
- if not endTime:
- endTime = datetime.datetime.now()
- else:
- endTime = get_tomorrow_zero_time(datetime.datetime.strptime(endTime, "%Y-%m-%d"))
- if not startTime:
- startTime = get_zero_time(endTime)
- else:
- startTime = get_zero_time(datetime.datetime.strptime(startTime, "%Y-%m-%d"))
- if startTime > endTime:
- startTime = endTime
- orderStatus = payload.get("orderStatus")
- groupInfo = payload.get("group", dict())
- deviceInfo = payload.get("device", dict())
- queryFilters = {
- 'dateTimeAdded': {
- '$gte': startTime,
- '$lt': endTime
- },
- "via": {
- "$in": map(format, [
- USER_RECHARGE_TYPE.RECHARGE_MIX,
- USER_RECHARGE_TYPE.RECHARGE,
- USER_RECHARGE_TYPE.RECHARGE_CARD,
- USER_RECHARGE_TYPE.RECHARGE_VIRTUAL_CARD,
- USER_RECHARGE_TYPE.RECHARGE_CASH,
- USER_RECHARGE_TYPE.RECHARGE_MONTHLY_PACKAGE,
- USER_RECHARGE_TYPE.RECHARGE_REDPACK,
- USER_RECHARGE_TYPE.RECHARGE_INSURANCE
- ])
- }
- }
- search_key = payload.get('searchKey', None)
- if search_key:
- if len(search_key) < 15:
- dev = Device.get_dev_by_logicalCode(search_key)
- if dev:
- queryFilters.update({'devNo': dev.devNo})
- if 'devNo' not in queryFilters:
- queryFilters.update({
- '$or': [
- {'orderNo': search_key},
- {'wxOrderNo': search_key},
- {'transactionId': search_key}
- ]
- })
- else:
- # 订单的状态
- if orderStatus:
- queryFilters.update({"result": orderStatus})
- # 查找的逻辑 自下从上查找 依次是 设备 --> 组 --> 当前查询人 --> 空查询
- # TODO 这个地方的信息安全性 完全依赖上次调度的接口, 目前没有做检查 记得加上
- if deviceInfo:
- queryFilters.update({"devNo": deviceInfo.get("devNo"), "ownerId": deviceInfo.get("ownerId")})
- elif groupInfo:
- queryFilters.update({"groupId": groupInfo.get("groupId"), "ownerId": groupInfo.get("ownerId")})
- else:
- # TODO 这个地方有个BUG 经销商的ID 防止部分新加入的组合伙人 能看到之前组的经营统计信息
- groupIds = list(set(Group.get_group_ids_of_dealer_and_partner(ownerId)))
- groups = Group.get_groups_by_group_ids(groupIds)
- dealer_id_list = list(set([group['ownerId'] for group in groups.values()]))
- queryFilters.update({
- 'ownerId': {'$in': dealer_id_list},
- 'groupId': {'$in': groupIds}
- })
- logger.debug('query recharges between {} and {}. filters = {}'.format(startTime, endTime, queryFilters))
- # 添加筛选条件 选出不是交易子单的订单
- query_set = RechargeRecord.objects.filter(__raw__=queryFilters).filter(attachParas__tradeOrderId=None).order_by('-dateTimeAdded') # type: CustomQuerySet
- totalSum = query_set.sum(RechargeRecord.money.name)
- total_count = query_set.count()
- records = query_set.paginate(pageIndex, pageSize)
- dataList = list()
- for _item in records: # type: RechargeRecord
- # 订单的基本信息
- data = {
- 'id': str(_item.id),
- 'ownerId': _item.ownerId,
- 'gateway': _item.gateway if _item.gateway else 'wechat',
- 'result': _item.result if _item.result else '',
- 'totalFee': _item.money if _item.money else 0,
- 'address': _item.address if _item.address else '',
- 'name': _item.groupName if _item.groupName else '',
- 'nickname': _item.nickname if _item.nickname else '',
- 'devTypeName': _item.dev_type_name,
- 'groupNumber': _item.groupNumber if _item.groupNumber else '',
- 'value': Device.get_logicalCode_by_devNo(_item.devNo) if _item.devNo else '',
- 'wechatTrxid': _item.wxOrderNo if _item.wxOrderNo else '',
- 'outTradeNo': _item.orderNo if _item.orderNo else '',
- 'createdTime': _item.to_datetime_str(_item.dateTimeAdded),
- 'description': _item.my_description if _item.my_description else '',
- 'userId': _item.openId if _item.openId else '',
- 'groupId': _item.groupId if _item.groupId else '',
- 'via': _item.via if _item.via else '',
- 'isQuickPay': _item.isQuickPay if _item.isQuickPay else False,
- 'startKey': _item.attachParas.get('startKey', '') if _item.result == 'success' else '',
- 'consumeId': _item.attachParas.get('consumeRecordId', ''),
- 'isLedgered': _item.is_ledgered,
- 'notLedgerDesc': _item.notLedgerDesc
- }
- # TODO 需要修改 加上子订单的信息
- tradeOrders = RechargeRecord.objects.filter(
- openId=_item.openId,
- attachParas__tradeOrderId=str(_item.id)
- )
- _subs = list()
- for _trade in tradeOrders: # type: RechargeRecord
- _subData = {
- 'id': str(_trade.id),
- 'ownerId': _trade.ownerId,
- 'gateway': _trade.gateway if _trade.gateway else 'wechat',
- 'result': _trade.result if _trade.result else '',
- 'totalFee': _trade.money if _trade.money else 0,
- 'address': _trade.address if _trade.address else '',
- 'name': _trade.groupName if _trade.groupName else '',
- 'nickname': _trade.nickname if _trade.nickname else '',
- 'devTypeName': _trade.dev_type_name,
- 'groupNumber': _trade.groupNumber if _trade.groupNumber else '',
- 'value': Device.get_logicalCode_by_devNo(_trade.devNo) if _trade.devNo else '',
- 'wechatTrxid': _trade.wxOrderNo if _trade.wxOrderNo else '',
- 'outTradeNo': _trade.orderNo if _trade.orderNo else '',
- 'createdTime': _trade.to_datetime_str(_trade.dateTimeAdded),
- 'description': _trade.my_description if _trade.my_description else '',
- 'userId': _trade.openId if _trade.openId else '',
- 'groupId': _trade.groupId if _trade.groupId else '',
- 'via': _trade.via if _trade.via else '',
- 'isQuickPay': _trade.isQuickPay if _trade.isQuickPay else False,
- 'startKey': _trade.attachParas.get('startKey', '') if _trade.result == 'success' else '',
- 'consumeId': _trade.attachParas.get('consumeRecordId', ''),
- 'isLedgered': _trade.is_ledgered,
- 'notLedgerDesc': _trade.notLedgerDesc
- }
- _subs.append(_subData)
- data["subs"] = _subs
- dataList.append(data)
- return JsonResponse({
- "result": 1,
- "description": "",
- 'payload': {
- "page": pageIndex,
- "pageSize": pageSize,
- "total": total_count,
- "totalSum":totalSum,
- "items": dataList
- }
- })
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'查询错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def consumeOrderRecords(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 经销商后台查询消费订单
- :param request:
- :return:
- """
- ownerId = str(request.user.bossId)
- payload = json.loads(request.body)
- pageIndex = payload.get("pageIndex")
- pageSize = payload.get("pageSize")
- startTime = payload.get("startTime")
- endTime = payload.get("endTime")
- if not endTime:
- endTime = datetime.datetime.now()
- else:
- endTime = get_tomorrow_zero_time(datetime.datetime.strptime(endTime, "%Y-%m-%d"))
- if not startTime:
- startTime = get_zero_time(endTime)
- else:
- startTime = get_zero_time(datetime.datetime.strptime(startTime, "%Y-%m-%d"))
- if startTime > endTime:
- startTime = endTime
- groupInfo = payload.get("group", dict())
- deviceInfo = payload.get("device", dict())
- filters = {
- 'dateTimeAdded': {
- '$gte': startTime,
- '$lt': endTime
- }
- }
- search_key = payload.get('searchKey', None)
- if search_key:
- if len(search_key) < 15:
- dev = Device.get_dev_by_logicalCode(search_key)
- if dev:
- filters.update({'devNo': dev.devNo})
- if 'devNo' not in filters:
- filters.update({
- 'orderNo': search_key
- })
- else:
- # 查找的逻辑 自下从上查找 依次是 设备 --> 组 --> 当前查询人 --> 空查询
- # TODO 这个地方的信息安全性 完全依赖上次调度的接口, 目前没有做检查 记得加上
- if deviceInfo:
- filters.update({"devNo": deviceInfo.get("devNo"), "ownerId": deviceInfo.get("ownerId")})
- elif groupInfo:
- filters.update({"groupId": groupInfo.get("groupId"), "ownerId": groupInfo.get("ownerId")})
- else:
- # TODO 这个地方有个BUG 经销商的ID 防止部分新加入的组合伙人 能看到之前组的经营统计信息
- groupIds = list(set(Group.get_group_ids_of_dealer_and_partner(ownerId)))
- groups = Group.get_groups_by_group_ids(groupIds)
- dealer_id_list = list(set([group['ownerId'] for group in groups.values()]))
- filters.update({
- 'ownerId': {'$in': dealer_id_list},
- 'groupId': {'$in': groupIds}
- })
- logger.debug('query consumes between {} and {}. filters = {}'.format(startTime, endTime, filters))
- records = ConsumeRecord.objects.filter(__raw__=filters).order_by("-dateTimeAdded") # type: CustomQuerySet
- count = records.count()
- dataList = []
- for rcd in records.paginate(pageIndex, pageSize):
- try:
- dataList.append(rcd.to_detail())
- except Exception as e:
- logger.exception(e)
- continue
- return JsonOkResponse(payload={"dataList": dataList, "total": count})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def discountRuleData(request):
- # type: (WSGIRequest)->JsonResponse
- groupId = request.GET.get('groupId', None)
- ownerId = str(request.user.bossId)
- if groupId is None:
- ruleList = []
- for k, v in request.user.format_default_discount.items():
- ruleList.append({'ruleId': k, 'payAmount': k, 'coins': v})
- return JsonResponse({"result": 1,
- "description": None,
- 'payload': {"ruleList": ruleList, "groupData": {}}})
- else:
- group = Group.get_group(groupId)
- if group is None:
- return JsonResponse({"result": 0, "description": u"找不到组", 'payload': {}})
- devNos = Device.get_devNos_by_group([groupId])
- group['equipmentCount'] = len(devNos)
- if ownerId == group['ownerId']:
- group['isManager'] = True
- else:
- group['isManager'] = False
- ruleList = []
- for k, v in group['ruleDict'].items():
- ruleList.append({'ruleId': k, 'payAmount': k, 'coins': v})
- return JsonResponse({"result": 1,
- "description": None,
- 'payload': {"ruleList": ruleList, "groupData": group}})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def discountCardRuleData(request):
- """
- 经销商端的卡优惠获取显示
- # 新的规则修改为
- 如果经销商设置有卡优惠规则 返还卡优惠规则
- 如果经销商没有设置卡优惠规则 但是设置有金币优惠规则 返还金币优惠规则
- 两个都没有设置 默认卡优惠规则
- :param request:
- :return:
- """
- groupId = request.GET.get("groupId", None)
- # 没有组ID的情况获取的是经销商的默认 优惠套餐
- ruleList = list()
- if not groupId:
- for k, v in request.user.format_card_discount.items():
- ruleList.append({"ruleId": k, "payAmount": k, "coins": v})
- return JsonOkResponse(payload={"ruleList": ruleList, "groupData": {}})
- group = Group.get_group(groupId)
- if not group:
- return JsonErrorResponse(description=u"错误的地址信息")
- # 经销商没有设置过卡的优惠规则
- if not group.get("cardRuleDict"):
- cardRuleDict = request.user.defaultCardDiscountConfig
- Group.objects.filter(id=groupId).update(cardRuleDic=cardRuleDict)
- Group.CacheMgr.invalid_group_cache([groupId])
- group = Group.get_group(groupId)
- devNos = Device.get_devNos_by_group([groupId])
- ownerId = str(request.user.bossId)
- group['equipmentCount'] = len(devNos)
- if ownerId == group['ownerId']:
- group['isManager'] = True
- else:
- group['isManager'] = False
- ruleList = []
- for k, v in group['cardRuleDict'].items():
- ruleList.append({'ruleId': k, 'payAmount': k, 'coins': v})
- return JsonResponse({"result": 1,
- "description": None,
- 'payload': {"ruleList": ruleList, "groupData": group}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'更新错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def saveDiscountRule(request):
- # type: (WSGIRequest)->JsonResponse
- """
- TODO TO REFACTOR
- :param request:
- :return:
- """
- currentDealer = request.user # type: cast(Dealer)
- # 校验优惠规则
- def check_rule_data(fields, rules):
- for ruleDict in rules:
- for field in fields:
- if len(str(ruleDict[field])) > 12:
- return False, u"%s数额超过限制" % ruleDict[field]
- try:
- float(ruleDict[field])
- except ValueError:
- return False, u"%s类型错误,请输入数字" % ruleDict[field]
- return True, u''
- def update_rule(ruleDict, rules):
- isNewlyAdded = lambda d: d["payAmount"] not in ruleDict.keys()
- if len(ruleDict) >= 10 and any(map(isNewlyAdded, rules)):
- raise ParameterError(u'最多只能设置10条优惠充值信息')
- for rule in rules:
- if rule['ruleId']:
- ruleDict.pop(str(rule['ruleId']), None)
- if rule['ruleId'] != 0 and (float(rule['coins']) in ruleDict.values()):
- raise ParameterError(u'同一套餐下,不能出现充不一样的钱,但是兑币的数目却相同')
- ruleDict.update({str(rule['payAmount']): float(rule['coins'])})
- return ruleDict
- payload = json.loads(request.body) if request.body else {}
- ruleList = payload.get('ruleData', None)
- if ruleList is None:
- return JsonErrorResponse(description=u'没有找到正确的规则')
- status, msg = check_rule_data(["payAmount", "coins"], ruleList)
- if not status:
- return JsonErrorResponse(description=msg)
- groupId = payload.get('groupId', None)
- # groupId为空表示修改默认充值套餐
- if groupId is None:
- try:
- newRuleDict = update_rule(currentDealer.format_default_discount, ruleList)
- currentDealer.update(defaultDiscountConfig=newRuleDict)
- return JsonResponse({"result": 1, "description": '', 'payload': {}})
- except ParameterError as e:
- return JsonErrorResponse(description=e.message)
- else:
- try:
- group = Group.objects(id=groupId).first() # type: Group
- if not group:
- return JsonErrorResponse(description=u'组不存在,请刷新后再试')
- isRecovery = payload.get('isRecovery', 'N')
- if isRecovery == 'Y':
- rule_dict = currentDealer.format_default_discount
- else:
- rule_dict = group.format_rule_dict
- update_rule(rule_dict, ruleList)
- Group.update_group(group_id=groupId, ruleDict=rule_dict)
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- except ParameterError as e:
- return JsonErrorResponse(description=e.message)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"更新错误"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def saveDiscountCardData(request):
- """
- 保存卡优惠设置
- :param request:
- :return:
- """
- def _check(rules, fieldnames=None):
- """
- 校验 ruleList 的每一个字段和字段值
- :param rules:
- :param fieldnames:
- :return:
- """
- if fieldnames is None:
- fieldnames = ["payAmount", "coins"]
- for ruleDict in rules:
- for field in fieldnames:
- if len(str(ruleDict[field])) > 12:
- return False, u"%s数额超过限制" % ruleDict[field]
- try:
- float(ruleDict[field])
- except ValueError:
- return False, u"%s类型错误,请输入数字" % ruleDict[field]
- return True, u""
- def _update(ruleDict, rules):
- """
- 更新优惠套餐
- :param ruleDict:
- :param rules:
- :return:
- """
- isNewlyAdded = lambda d: d["payAmount"] not in ruleDict.keys()
- if len(ruleDict) >= 10 and any(map(isNewlyAdded, rules)):
- raise ParameterError(u'最多只能设置10条优惠充值信息')
- for rule in rules:
- if rule['ruleId']:
- ruleDict.pop(str(rule['ruleId']), None)
- if rule['ruleId'] != 0 and (float(rule['coins']) in ruleDict.values()):
- raise ParameterError(u'同一套餐下,不能出现充不一样的钱,但是兑币的数目却相同')
- ruleDict.update({str(rule['payAmount']): float(rule['coins'])})
- return ruleDict
- payload = json.loads(request.body) if request.body else dict()
- ruleList = payload.get("ruleData", None)
- if ruleList is None:
- return JsonErrorResponse(description=u"请设置正确的优惠规则")
- status, msg = _check(ruleList)
- if not status:
- return JsonErrorResponse(description=msg)
- groupId = payload.get("groupId", None)
- if groupId is None:
- try:
- newDict = _update(request.user.format_card_discount, ruleList)
- request.user.update(defaultCardDiscountConfig=newDict)
- except ParameterError as e:
- return JsonErrorResponse(description=e.message)
- else:
- return JsonOkResponse(payload={})
- else:
- try:
- group = Group.objects(id=groupId).first() # type: Group
- if not group:
- return JsonErrorResponse(description=u'组不存在,请刷新后再试')
- isRecovery = payload.get('isRecovery', 'N')
- # if isRecovery == 'Y':
- # rule_dict = request.user.format_card_discount
- # else:
- rule_dict = group.format_card_dict
- newDict = _update(rule_dict, ruleList)
- Group.update_group(group_id=groupId, cardRuleDict=newDict)
- except ParameterError as e:
- return JsonErrorResponse(description=e.message)
- else:
- return JsonOkResponse(payload={})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def delDiscountRule(request):
- # type: (WSGIRequest)->JsonResponse
- ruleId = request.POST.get('ruleId', None)
- if not ruleId:
- return JsonResponse({"result": 0, "description": u"缺少参数ruleId或为空", 'payload': {}})
- groupId = request.POST.get('groupId', None)
- if not groupId:
- default_discount = request.user.format_default_discount
- default_discount.pop(ruleId, None)
- request.user.update(defaultDiscountConfig=default_discount)
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- else:
- try:
- group = Group.objects(id=str(groupId)).first()
- if not group:
- return JsonResponse({"result": 0, "description": u"组不存在,请刷新后再试", 'payload': {}})
- rule_dict = group.format_rule_dict # type: dict
- rule_dict.pop(ruleId, None)
- Group.update_group(group_id=groupId, ruleDict=rule_dict)
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- except Exception, e:
- logger.exception("update db error=%s,groupId=%s" % (e, groupId))
- return JsonResponse({"result": 0, "description": u"更新异常,请重试", 'payload': {}})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def delDiscountCardData(request):
- """
- 删除卡优惠设置
- :param request:
- :return:
- """
- ruleId = request.POST.get('ruleId', None)
- if not ruleId:
- return JsonResponse({"result": 0, "description": u"缺少参数ruleId或为空", 'payload': {}})
- groupId = request.POST.get('groupId', None)
- if not groupId:
- default_discount = request.user.format_card_discount
- default_discount.pop(ruleId, None)
- request.user.update(defaultCardDiscountConfig=default_discount)
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- else:
- try:
- group = Group.objects(id=str(groupId)).first()
- if not group:
- return JsonResponse({"result": 0, "description": u"组不存在,请刷新后再试", 'payload': {}})
- rule_dict = group.format_card_dict # type: dict
- rule_dict.pop(ruleId, None)
- Group.update_group(group_id=groupId, cardRuleDict=rule_dict)
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- except Exception, e:
- logger.exception("update db error=%s,groupId=%s" % (e, groupId))
- return JsonResponse({"result": 0, "description": u"更新异常,请重试", 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取经销商信息错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def accountInfo(request):
- # type: (WSGIRequest)->JsonResponse
- if check_role(request.user, ROLE.dealer):
- dealer = Dealer.objects(id=str(request.user.bossId)).get() # type: Dealer
- payload = dealer.to_dict()
- else:
- subaccount = SubAccount.objects(id=str(request.user.id)).get() # type: subaccount
- payload = subaccount.to_dict()
- agent = Agent.objects(id=payload['agentId']).first() # type: Agent
- payload['servicePhone'] = agent.service_phone
- payload['serviceQrcodeUrl'] = agent.serviceQrcodeUrl
- return JsonResponse({"result": 1, "description": None, 'payload': payload})
- ####`经销商金融版块(提现,银行卡信息)` ####################################################
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def walletData(request):
- # type: (WSGIRequest)->JsonResponse
- dealerId = str(request.user.bossId)
- dealer = Dealer.objects(id=dealerId).first() # type: Optional[Dealer]
- if not dealer:
- return JsonErrorResponse(description=u"没有找到经销商")
- my_source_key = dealer.current_wallet_withdraw_source_key
- inhouse_source_key = Agent.get_inhouse_prime_agent().current_wallet_withdraw_source_key
- device_income_list = []
- for source_key, balance in dealer.deviceBalance.iteritems():
- if WithdrawGateway.is_ledger(source_key) and balance.balance != RMB(0):
- device_income_list.append({
- 'id': source_key,
- 'balance': balance.balance,
- 'name': current_platform(source_key, my_source_key),
- 'current': source_key == my_source_key
- })
- ad_income_list = []
- for source_key, balance in dealer.adBalance.iteritems():
- if WithdrawGateway.is_ledger(source_key) and balance.balance != RMB(0):
- ad_income_list.append({
- 'id': source_key,
- 'balance': balance.balance,
- 'name': current_platform(source_key, inhouse_source_key),
- 'current': source_key == inhouse_source_key
- })
- ledger_income_list = []
- for source_key, balance in dealer.ledgerBalance.iteritems():
- if WithdrawGateway.is_ledger(source_key) and balance.balance != RMB(0):
- ledger_income_list.append({
- 'id': source_key,
- 'balance': balance.balance,
- 'name': current_platform(source_key, inhouse_source_key),
- 'current': source_key == inhouse_source_key
- })
- payload = {
- }
- if len(device_income_list) > 0:
- payload.update({
- DEALER_INCOME_TYPE.DEVICE_INCOME: device_income_list
- })
- if len(ad_income_list) > 0:
- payload.update({
- DEALER_INCOME_TYPE.AD_INCOME: ad_income_list
- })
- if len(ledger_income_list) > 0:
- payload.update({
- DEALER_INCOME_TYPE.LEDGER_CONSUME: ledger_income_list
- })
- return JsonResponse({'result': 1, 'description': '', 'payload': payload})
- # 经销商获取提现短信验证码
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getWithdrawCode(request):
- # type: (WSGIRequest)->JsonResponse
- currentDealer = request.user # type: Dealer
- toNumber = request.user.username
- agentId = request.user.agentId
- agent = Agent.get_agent(agentId)
- productName = agent['productName']
- if not currentDealer.monitorPhone: # 没有监管的,直接发送验证码到本机
- status, msg = dealerWithdrawSMSProvider.get(phoneNumber=toNumber,
- productName=productName,
- vendor=SysParas.get_sms_vendor(request.user.smsVendor))
- else:
- toNumber = currentDealer.monitorPhone
- status, msg = dealerMonitorWithdrawSMSProvider.get(phoneNumber=toNumber,
- productName=productName,
- vendor=SysParas.get_sms_vendor(request.user.smsVendor))
- if not status:
- return JsonErrorResponse(description=msg)
- else:
- return JsonOkResponse()
- @permission_required(ROLE.dealer)
- def withdrawalsHistoryList(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 需要连同整个提现数据层整改
- :param request:
- :return:
- """
- current_user = request.user # type: Dealer
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- status = request.GET.get('status')
- ownerId = str(request.user.bossId)
- startTime = '2016-01-01'
- startTime, _ = current_user.limit_filter_date(startTime, None)
- startTime = datetime.datetime.strptime(startTime, "%Y-%m-%d")
- if status:
- records = WithdrawRecord.objects(ownerId=ownerId,
- role=request.user.role,
- status=status,
- postTime__gte=startTime).order_by('-postTime')
- else:
- records = WithdrawRecord.objects(ownerId=ownerId,
- role=request.user.role,
- postTime__gte=startTime).order_by('-postTime')
- return JsonResponse({
- "result": 1,
- "description": None,
- 'payload': {
- "total": records.count(),
- "withdrawalTotal": RMB(records(status=WithdrawStatus.SUCCEEDED).sum('amount')),
- "dataList": [
- {
- 'bankName': record.parentBankName,
- 'paymentId': str(record.id),
- 'withdrawalsDate': record.postTime.strftime("%Y-%m-%d %H:%M:%S"),
- 'amount': record.amount,
- 'statusText': translate_withdraw_state(record.status),
- 'refunded': record.refunded
- } for record in records.paginate(pageIndex, pageSize)
- ]
- }
- })
- @permission_required(ROLE.dealer)
- def dealerWithdraw(request):
- # type: (WSGIRequest)->JsonResponse
- """
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- pay_type = payload.get('payType')
- assert pay_type in (
- WITHDRAW_PAY_TYPE.WECHAT, WITHDRAW_PAY_TYPE.BANK, WITHDRAW_PAY_TYPE.ALIPAY), 'not support this pay type'
- if pay_type == WITHDRAW_PAY_TYPE.WECHAT:
- open_id = payload.get('openId')
- if not open_id:
- return JsonResponse({"result": 0, "description": u'鉴权失败,请刷新后再试', 'payload': {}})
- request.user.withdraw_open_id = open_id
- amount = RMB(payload.get('amount', 0.0))
- assert amount > RMB(0), 'amount must be bigger than zero'
- status, msg = request.user.withdraw_sms_provider.verify(phoneNumber = request.user.withdraw_sms_phone_number,
- smsCode = payload.get('code'))
- if not status:
- return JsonResponse({"result": 0, "description": msg, 'payload': {}})
- withdraw_service = DealerWithdrawService(payee = request.user,
- income_type = payload.get('sourceType'),
- amount = amount,
- pay_type = pay_type,
- bank_card_no = payload.get('bankAccount', ''))
- result = withdraw_service.execute(source_key = payload.get('sourceId'), recurrent = False)
- logger.debug('withdraw result is: {}'.format(result))
- return JsonResponse(result)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def paymentInfo(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 展示提现页面数据
- :param request:
- :return:
- """
- ownerId = str(request.user.bossId)
- paymentId = request.GET.get('paymentId', None)
- if not paymentId:
- return JsonErrorResponse(description=u'没有提供提现单ID')
- record = WithdrawRecord.objects(id=str(paymentId)).first() # type: Optional[WithdrawRecord]
- if not record:
- return JsonErrorResponse(description=u"没有找到提现记录")
- return JsonOkResponse(
- payload={
- 'type': record.parentBankName,
- 'amount': record.amount,
- 'preBalance': record.balance,
- 'serviceFee': record.serviceFee,
- 'actualPay': record.actualPay,
- 'refunded': record.refunded,
- 'statusText': translate_withdraw_state(record.status),
- 'description': record.description,
- 'withdrawalsDate': record.postTime.strftime("%Y-%m-%d %H:%M:%S")
- }
- )
- @permission_required(ROLE.dealer)
- def getDealerAutoWithdrawCode(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 经销商确认开启自动提现
- :param request:
- :return:
- """
- try:
- phoneNumber = request.GET.get('phoneNumber', None)
- if not phoneNumber:
- return JsonErrorResponse(description=u'手机号码为空')
- agent = Agent.get_agent(request.user.agentId)
- productName = agent['productName']
- status, msg = dealerAutoWithdrawSMSProvider.get(phoneNumber=phoneNumber,
- productName=productName,
- vendor=SysParas.get_sms_vendor(request.user.smsVendor))
- if not status:
- return JsonErrorResponse(description=msg)
- else:
- return JsonOkResponse()
- except Exception as e:
- logger.exception(e)
- return JsonErrorResponse()
- #### `Utils related` ###########################################################
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def deviceMem(request):
- # type: (WSGIRequest)->JsonResponse
- logicalCode = request.GET.get('logicalCode')
- if not logicalCode:
- return JsonErrorResponse(description=u'未提供设备逻辑编码')
- devNo = Device.get_devNo_by_logicalCode(logicalCode)
- dev = Device.get_dev(devNo)
- return JsonResponse(dev)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def deviceInfo(request):
- # type: (WSGIRequest)->JsonResponse
- logicalCode = request.GET.get('logicalCode', '')
- devNo = Device.get_devNo_by_logicalCode(logicalCode)
- dev = Device.get_dev(devNo)
- if dev is None:
- return JsonErrorResponse(description=u'设备不存在')
- return JsonResponse(MessageSender.send(dev, DeviceCmdCode.GET_DEVINFO, {'IMEI': devNo}))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getServiceInfo(request):
- # type: (WSGIRequest)->JsonResponse
- currentDealer = request.user.myBoss # type: Optional[Dealer]
- if not currentDealer:
- return JsonResponse({"result": 0, "description": u"没有找到经销商"})
- value = {
- "qrcodeUrl": currentDealer.qrcodeUrl,
- "serviceName": currentDealer.serviceName,
- "servicePhone": currentDealer.servicePhone
- }
- return JsonResponse({"result": 1, "description": "", 'payload': value})
- @permission_required(ROLE.dealer)
- def saveServiceInfo(request):
- # type: (WSGIRequest)->JsonResponse
- ownerId = request.user.bossId # type: ObjectId
- qrcodeUrl = request.POST.get('qrcodeUrl')
- serviceName = request.POST.get('serviceName')
- if serviceName:
- if NAME_RE.match(serviceName) is None:
- logger.error('name formatting error, name=%s' % serviceName)
- return JsonResponse({"result": 0, "description": u"请输入正确格式的名称, 2-20位"})
- servicePhone = request.POST.get('servicePhone')
- if servicePhone:
- if PHONE_NUMBER_RE.match(servicePhone) is None:
- logger.error('phone number format error, phone=%s' % servicePhone)
- return JsonResponse({"result": 0, "description": u"请输入正确的手机号码"})
-
- status, desc = dealerRegisterSMSProvider.verify(servicePhone, request.POST.get('code'))
- if not status:
- return JsonErrorResponse(desc)
- result = Dealer.update_dealer(ownerId, qrcodeUrl=qrcodeUrl, serviceName=serviceName, servicePhone=servicePhone)
- if not result:
- return JsonResponse({"result": 0, "description": u"更新经销商服务信息错误"})
- return JsonResponse({"result": 1, "description": "", 'payload': {}})
- # : 报告老板
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def userFeedbackRecords(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 获取用户反馈记录
- :param request:
- :return:
- """
- ownerId = str(request.user.bossId)
- searchKey = request.GET.get('searchKey', '')
- feedType = request.GET.get('feedType', '')
- pageIndex = int(request.GET.get('pageIndex', '1'))
- pageSize = int(request.GET.get('pageSize', '10'))
- status = request.GET.get('status', None)
- if status and status != 'null':
- status = int(status)
- else:
- status = None
- dateStart = request.GET.get('dateStart', '')
- if dateStart == '':
- startTime = '2000-01-01 00:00:00'
- else:
- startTime = dateStart + " 00:00:00"
- dateEnd = request.GET.get('dateEnd', '')
- if dateEnd == '':
- endTime = '2100-01-01 00:00:00'
- else:
- endTime = dateEnd + " 23:59:59"
- query = {
- 'ownerId': str(ownerId),
- '$and': [
- {
- 'createTime': {
- '$gte': startTime
- }
- },
- {
- 'createTime': {
- '$lte': endTime
- }
- },
- ],
- }
- if feedType:
- if feedType == 'other':
- feed_type_list = ['refund', 'upper']
- query.update({
- 'feedType': {'$in': feed_type_list},
- 'consumeRecordOrderNo': {'$in': [None, '']}
- })
- else:
- feed_type_list = [feedType]
- query.update({
- 'feedType': {'$in': feed_type_list}
- })
- if status is not None:
- query.update({
- 'status': status
- })
- results = FeedBack.objects(__raw__ = query).search(searchKey).order_by('-createTime')
- total = results.count()
- rv = []
- for item in results.paginate(pageIndex, pageSize): # type: FeedBack
- rv.append(item.summary)
- data = {'page': pageIndex, 'total': total, 'pageSize': pageSize, 'items': rv}
- return JsonResponse({'result': 1, 'description': "", 'payload': data})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def userFeedbackInfo(request):
- # type: (WSGIRequest)->JsonResponse
- fdId = str(request.GET.get('id'))
- fd = FeedBack.objects(id = fdId).first() # type: FeedBack
- if not fd:
- return JsonResponse({'result': 0, 'description': u"投诉订单不存在,请刷新页面重试", 'payload': {}})
- else:
- return JsonResponse({'result': 1, 'description': "", 'payload': fd.detail})
- @error_tolerate(logger = logger, nil = JsonErrorResponse(u'处理失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def userFeedbackHandle(request):
- # type: (WSGIRequest)->JsonResponse
- """
- :param request:
- :return:
- """
- payload = json.loads(request.body) if request.body else {}
- if not payload:
- return JsonErrorResponse(description = u'传入数据为空')
- action = payload.get('action')
- if not action:
- return JsonOkResponse()
- dealerRemark = payload.get('dealerRemark', u'(未填写回复内容)')
- dealerImgList = payload.get('dealerImgList', [])
- options = {} if dealerRemark is None else {'dealerRemark': dealerRemark, 'dealerImgList': dealerImgList}
- feedback = FeedBack.objects(id = payload['id']).first() # type: Optional[FeedBack]
- if not feedback:
- return JsonErrorResponse(description = u'没有找到该反馈单')
- dealer = Dealer.objects(id = feedback.ownerId).first() # type: Optional[Dealer]
- if not dealer:
- return JsonErrorResponse(description = u'未找到该反馈单的经销商')
- feedType = feedback.feedType
- if feedback.my_logicalCode:
- device = Device.objects(logicalCode = feedback.my_logicalCode).first() # type: Optional[Device]
- else:
- device = None
- if not device:
- return JsonErrorResponse(description = u'找不到相关设备')
- wechat_mp_proxy = get_wechat_user_manager_mp_proxy(dealer) # type: WechatClientProxy
- user = MyUser.objects(openId = feedback.openId, groupId = feedback.my_group_id).first() # type: Optional[MyUser]
- if not user:
- logger.warning('user<openId={}> not exists for feedback<id={}>'.format(feedback.openId, str(feedback.id)))
- if action in ['close', 'reject']:
- feedback.handle(action, **options)
- wechat_mp_proxy.notify(user.managerialOpenId, 'feedback_process', **{
- 'title': u'您反馈的问题已经处理' if action == 'close' else u'您反馈的问题已经被驳回',
- 'event': '%s:%s' % (feedback.message_type, feedback.description),
- 'remark': '%s: %s' % (u'设备老板回复', dealerRemark),
- 'finishTime': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- }) if user else None
- return JsonOkResponse()
- elif action == 'stop':
- assert feedType == 'fault', u'投诉类型错误'
- device.set_fault()
- feedback.handle(action, **options)
- wechat_mp_proxy.notify(user.managerialOpenId, 'feedback_process', **{
- 'title': u'您反馈的问题已经处理',
- 'event': u'设备已经暂停使用,等待维修中',
- 'remark': '%s: %s' % (u'设备老板回复', dealerRemark),
- 'finishTime': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- }) if user else None
- return JsonResponse({'result': 1, 'description': "", 'payload': {}})
- elif action == 'refund':
- if not user:
- return JsonErrorResponse(description = u'用户不存在,无法派币')
- agent = Agent.objects.get(id = request.user.agentId)
- if 'coinIsMoney' in agent.features:
- return JsonResponse({'result': 2, 'description': u"代理商的配置,不允许给用户派币", 'payload': {}})
- refundCoins = VirtualCoin(payload.get('refundCoins'))
- if refundCoins > VirtualCoin(0):
- inced = user.incr_balance(refundCoins)
- if not inced:
- logger.error('failed to incr balance for %r' % (user,))
- return JsonErrorResponse(description = u'退币失败')
- RechargeRecord.from_feedback(feedback, refundCoins).save()
- feedback.handle(action, **options)
- wechat_mp_proxy.notify(user.managerialOpenId, 'feedback_process', **{
- 'title': u'您反馈的问题已经处理',
- 'event': u'%s:%s' % (feedback.message_type, feedback.description),
- 'remark': '%s: %s' % (u'设备老板回复', dealerRemark),
- 'finishTime': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- }) if user else None
- return JsonOkResponse()
- else:
- logger.warning('invalid action<value={}> for feedback<id=>'.format(action, str(feedback.id)))
- return JsonOkResponse()
- @error_tolerate(logger = logger, nil = JsonErrorResponse(u'处理失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def userFeedbackBatchHandle(request):
- # type: (WSGIRequest)->JsonResponse
- """
- :param request:
- :return:
- """
- payload = json.loads(request.body) if request.body else {}
- if not payload:
- return JsonErrorResponse(description = u'传入数据为空')
- dealerRemark = payload.get('dealerRemark')
- options = {} if dealerRemark is None else {'dealerRemark': dealerRemark}
- feedbacks = FeedBack.objects(id__in = payload['ids'])
- if feedbacks.count() == 0:
- return JsonErrorResponse(description = u'没有找到反馈单')
- for feedback in feedbacks:
- feedback.handle('close', **options)
- dealer = Dealer.objects(id = feedback.ownerId).first() # type: Optional[Dealer]
- if not dealer:
- logger.warning(
- 'not find this dealer<id={}> for feedback<id={}>'.format(feedback.ownerId, str(feedback.id)))
- continue
- wechat_mp_proxy = get_wechat_user_manager_mp_proxy(dealer) # type: WechatClientProxy
- user = MyUser.objects(openId = feedback.openId, groupId = feedback.my_group_id).first() # type: Optional[MyUser]
- if not user:
- logger.warning(
- 'not find this user<openId={}> for feedback<id={}>'.format(feedback.openId, str(feedback.id)))
- continue
- wechat_mp_proxy.notify(user.managerialOpenId, 'feedback_process', **{
- 'title': u'您反馈的问题已经处理',
- 'event': '%s:%s' % (feedback.message_type, feedback.description),
- 'finishTime': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- })
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getCustomerDetailInfo(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 获取用户部分详细信息,如累计充值
- :param request:
- :return:
- """
- customerOpenId = request.GET.get('id')
- if not customerOpenId:
- return JsonErrorResponse(description=u'传入用户ID为空,无法获取详情')
- ownerId = request.user.bossId
- groupIds = list(set(Group.get_group_ids_of_dealer_and_partner(ownerId)))
- users = MyUser.get_collection().find({"openId": customerOpenId, "groupId": {"$in": groupIds}})
- rechargeTotal = RMB(0)
- bestowTotal = RMB(0)
- consumptionTotal = RMB(0)
- balance = RMB(0)
- nickname = ""
- phone = ""
- openId = ""
- idStr = ""
- breakRuleTimes = 0
- orderRemindType = 2
- for user in users:
- nickname = user.get('nickname', "")
- balance += (RMB(user.get("chargeBalance", 0)) + RMB(user.get("bestowBalance", 0)))
- rechargeTotal += RMB(user.get("total_recharged", 0))
- bestowTotal += RMB(user.get("total_bestow", 0))
- consumptionTotal += RMB(user.get("total_consumed", 0))
- openId = user.get("openId", "")
- idStr = str(user.get('_id', ''))
- if user.get('blacklistConfig', {}).get('orderRemindType', 2) != 2:
- orderRemindType = user['blacklistConfig']['orderRemindType']
- if user.get('blacklistConfig', {}).get('breakRuleTimes', 0) != 0:
- breakRuleTimes = user['blacklistConfig']['breakRuleTimes']
- if breakRuleTimes > 0 and orderRemindType != 0:
- orderRemindType = 0
- us = MyUser.objects(openId=user['openId'], groupId__in=groupIds)
- for _ in us:
- _.blacklistConfig['orderRemindType'] = orderRemindType
- _.save()
- status = "black" if check_black_user(dealerId=str(ownerId), openId=openId) else "white"
- if idStr:
- user = MyUser.objects.filter(id=idStr).first()
- phone = user.phone
- return JsonResponse({
- 'result': 1,
- 'description': None,
- 'payload': {
- 'balance': balance,
- 'nickname': nickname,
- 'phone': phone,
- 'rechargeTotal': rechargeTotal,
- 'consumptionTotal': consumptionTotal,
- 'status': status,
- 'breakRuleTimes': breakRuleTimes,
- 'orderRemindType': orderRemindType
- }
- })
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getCustomerListUnderDealer(request):
- """ 获取经销商名下的用户 按照openId做归并 查询需要根据特性来决定是否做手机号码查询"""
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- searchKey = request.GET.get('searchKey', "")
- sortKey = request.GET.get('sortName', 'last_login')
- sortOrder = request.GET.get('sortType', 'des')
- isNew = True if request.GET.get('isNew', 'false') == 'true' else False
- ownerId = request.user.bossId
- groupIds = Group.get_group_ids_of_dealer_and_partner(ownerId=ownerId)
- # 获取用户默认头像
- default_avatar = Agent.get_agent(request.user.agentId).get("productLogo")
- sortFilters = True if sortOrder == "des" else False
- groupFilters = {
- "_id": "$openId",
- "chargeBalance": {"$sum": "$chargeBalance"},
- "bestowBalance": {"$sum": "$bestowBalance"},
- "total_recharged": {"$sum": "$total_recharged"},
- "total_bestow": {"$sum": "$total_bestow"},
- "total_consumed": {"$sum": "$total_consumed"},
- "nickname": {"$first": "$nickname"},
- "sex": {"$first": "$sex"},
- "avatar": {"$first": "$avatar"},
- "openId": {"$first": "$openId"},
- "last_login": {"$max": "$last_login"}
- }
- matchFilters = {
- "groupId": {"$in": groupIds}
- }
- by_phone = False
- by_user_id = False
- by_others = False
- if re.match(r'1[3-9][0-9]{9}$', searchKey):
- by_phone = True
- elif re.match(r'^[0-9]{5,10}$', searchKey):
- by_user_id = True
- else:
- by_others = True
- # 符合手机号码的正则
- if by_phone or by_user_id:
- if by_phone:
- agent = Agent.objects.filter(id = str(request.user.myBoss.agentId)).first() # type: Agent
- if agent.supports('user_identify'):
- user = MyUser.objects.filter(phoneNumber = searchKey).first()
- else:
- user = UniqueUser.objects.filter(phone = searchKey).first() # type: UniqueUser
- else:
- user = UniqueUser.objects.filter(userId=searchKey).first() # type: UniqueUser
- if not user:
- return JsonErrorResponse(description=u"未查询到该用户")
- matchFilters.update({
- 'openId': user.openId
- })
- else:
- startTime = request.GET.get('startTime', None)
- endTime = request.GET.get('endTime', None)
- if startTime:
- startDataTime = to_datetime(startTime + ' 00:00:00')
- now = datetime.datetime.now()
- if not endTime:
- endDateTime = now + datetime.timedelta(days=1)
- else:
- endDateTime = to_datetime(endTime, "%Y-%m-%d")
- if endDateTime > now:
- endDateTime = now
- endDateTime = endDateTime + datetime.timedelta(days=1)
- if startDataTime >= endDateTime:
- endDateTime = startDataTime + datetime.timedelta(days=1)
- timeFilters = {
- "$gte": startDataTime,
- "$lt": endDateTime
- }
- if isNew:
- timeKey = "dateTimeAdded"
- else:
- timeKey = "last_login"
- matchFilters.update({
- timeKey: timeFilters
- })
- if searchKey:
- matchFilters.update({
- "nickname": {"$regex": "%s" % searchKey}
- })
- users = MyUser.get_collection().aggregate([
- {"$match": matchFilters},
- {"$group": groupFilters},
- ])
- totalUsers = list(users)
- if sortKey == "last_login":
- totalUsers.sort(key=lambda x: x.get(sortKey), reverse=sortFilters)
- else:
- totalUsers.sort(key=lambda x: VirtualCoin(x.get(sortKey)), reverse=sortFilters)
- tempUsers = totalUsers[(pageIndex - 1) * pageSize: pageIndex * pageSize]
- for user in tempUsers:
- if not user["avatar"]: user["avatar"] = default_avatar
- if 'total_recharged' in user:
- user['total_recharged'] = RMB(user['total_recharged'])
- if 'total_consumed' in user:
- user['total_consumed'] = RMB(user['total_consumed'])
- if 'chargeBalance' or 'bestowBalance' in user:
- user["chargeBalance"] = RMB(user.get("chargeBalance", 0))
- user["bestowBalance"] = RMB(user.get("bestowBalance", 0))
- user['balance'] = user['chargeBalance'] + user['bestowBalance']
- return JsonResponse({
- "result": 1,
- "description": None,
- "payload": {
- "total": len(totalUsers),
- "dataList": tempUsers
- }
- })
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getRechargeRecordByCustomer(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 由用户详情 查询用户的充值记录
- :param request:
- :return:
- """
- pageIndex = int(request.GET.get("pageIndex"))
- pageSize = int(request.GET.get("pageSize"))
- openId = request.GET.get("id")
- cardId = request.GET.get("cardTicketId") # 直接查看某一张虚拟卡的充值记录
- startTime = request.GET.get('startTime', Const.QUERY_START_DATE)
- endTime = request.GET.get('endTime', datetime.datetime.now().strftime('%Y-%m-%d'))
- if cardId:
- orderNoList = VirtualCardRechargeRecord.get_link_orderNo_list(
- cardId = cardId, startTime = to_datetime(startTime, '%Y-%m-%d'), endTime = to_datetime(endTime, '%Y-%m-%d'))
- queryFilter = {
- 'orderNo__in': orderNoList
- }
- else:
- queryFilter = {
- 'ownerId__in': Dealer.get_cooperative_dealer_ids(str(request.user.bossId)),
- "openId": openId,
- "result": "success",
- "via__in": map(format, [
- USER_RECHARGE_TYPE.RECHARGE,
- USER_RECHARGE_TYPE.RECHARGE_CARD,
- USER_RECHARGE_TYPE.RECHARGE_VIRTUAL_CARD,
- USER_RECHARGE_TYPE.RECHARGE_CASH,
- USER_RECHARGE_TYPE.RECHARGE_MONTHLY_PACKAGE
- ]),
- 'hint': [("openId", 1)]
- }
- records = RechargeRecord.objects.filter(
- dateTimeAdded__gte=to_datetime(startTime, '%Y-%m-%d'),
- dateTimeAdded__lt=to_datetime(endTime, '%Y-%m-%d'),
- **queryFilter
- )
- dataList = list()
- for record in records.paginate(pageIndex, pageSize):
- _data = {
- "gateway": record.gateway or 'wechat',
- "createdTime": record.created_date,
- "totalFee": record.money,
- "gatewayTradeNo": record.wxOrderNo,
- "outTradeNo": record.orderNo,
- "address": record.address,
- "name": record.groupName,
- "groupNumber": record.groupNumber,
- "devTypeName": record.dev_type_name,
- "logicalCode": record.logicalCode,
- "isQuickPay": record.isQuickPay,
- "result": getattr(record, "result", 'success'),
- "description": getattr(record, "description", ''),
- "via": record.via,
- "coins": record.coins
- }
- if "refundOrder" in request.user.features:
- _data["showRefund"] = (record.is_refund_available(request.user)) and (not record.has_refund_order)
- dataList.append(_data)
- total = pageIndex * pageSize if len(dataList) < pageSize else (pageIndex + 1) * pageSize
- return JsonResponse({'result': 1, 'description': "", 'payload': {'dataList': dataList, 'total': total}})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getConsumptionRecordByCustomer(request):
- # type: (WSGIRequest)->JsonResponse
- """
- :param request:
- :return:
- """
- pageIndex = int(request.GET.get("pageIndex", 1))
- pageSize = int(request.GET.get("pageSize", 10))
- openId = request.GET.get("id")
- groupId = request.GET.get("groupId")
- lastYear = datetime.date((datetime.date.today().year - 1), datetime.date.today().month,
- datetime.date.today().day).strftime("%Y-%m-%d")
- startTime = request.GET.get('startTime', lastYear)
- endTime = request.GET.get('endTime', datetime.datetime.now().strftime('%Y-%m-%d'))
- queryFilter = {"ownerId": str(request.user.bossId), "openId": openId}
- if groupId:
- queryFilter.update({"groupId": groupId})
- records = ClientConsumeModelProxy.get_data_list(startTime=startTime, endTime=endTime, **queryFilter)
- # 修改 列表仅仅展示基础数据 详细信息在详单中查询
- dataList = []
- for record in records.paginate(pageIndex, pageSize):
- newData = {
- "groupName": record.groupName,
- "groupNumber": record.groupNumber,
- "devTypeName": record.devTypeName,
- "logicalCode": record.logicalCode,
- "createdTime": record.dateTimeAdded,
- "orderNo": record.orderNo,
- "id": str(record.id),
- "ownerId": record.ownerId
- }
- newData.update(record.service)
- dev = Device.get_dev_by_logicalCode(record.logicalCode) # type: DeviceDict
- if dev and dev.is_registered and dev.ownerId == record.ownerId:
- if (record.devTypeCode or dev.devTypeCode) == Const.DEVICE_TYPE_CODE_HP_GATE: # 霍珀道闸分支
- newData.update({'desc': record.servicedInfo.get('oper', u'未知')})
- elif record.devTypeCode in support_policy_weifule + support_policy_device:
- if record.status != ConsumeRecord.Status.FINISHED:
- if (datetime.datetime.now() - record.dateTimeAdded).total_seconds() > 60 * 60 * 12:
- newData.update({'desc': '超12小时未结束'})
- if record.status == ConsumeRecord.Status.RUNNING:
- newData.update({'showStopButton': True})
- if record.status == ConsumeRecord.Status.END:
- newData.update({'showStopButton': True})
- else:
- continue
- dataList.append(newData)
- total = pageIndex * pageSize if len(dataList) < pageSize else (pageIndex + 1) * pageSize
- return JsonResponse({'result': 1, 'description': "", 'payload': {'dataList': dataList, 'total': total}})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def modifyCustomerBalance(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 给终端用户派币或扣币(通常情况不支持)
- :param request:
- :return:
- """
- currentDealer = request.user.myBoss # type: Optional[Dealer]
- agent = Agent.objects.filter(id=str(currentDealer.agentId)).first() # type: Agent
- if 'disable_dealer_onPoints_and_sendCoins' in agent.features:
- return JsonResponse(
- {'result': 0, 'description': '设备无法使用该功能奥, 如有问题, 请联系代理商', 'payload': {}})
- payload = json.loads(request.body) if request.body else {}
- if not payload: return JsonErrorResponse(description=u'传入数据为空')
- coins = VirtualCoin(payload.get('coins', 0.0))
- desc = payload.get('description')
- customerOpenId = payload.get('userId')
- groupId = payload.get('groupId')
- ownerId = str(currentDealer.bossId)
- operator = currentDealer.nickname
- customer = MyUser.objects(groupId=groupId, openId=customerOpenId).first() # type: Optional[MyUser]
- if not customer:
- return JsonResponse({'result': 0, 'description': u'该用户不存在', 'payload': {}})
- if coins < VirtualCoin(0) and -coins > customer.balance:
- return JsonResponse({'result': 0, 'description': u'最多只能扣除掉%s个币' % customer.balance, 'payload': {}})
- agent = Agent.objects.get(id=currentDealer.agentId)
- if 'coinIsMoney' in agent.features:
- return JsonResponse({'result': 0, 'description': u'代理商的配置,不允许给用户派币', 'payload': {}})
- group = Group.get_group(groupId)
- if group['ownerId'] != ownerId:
- return JsonResponse({'result': 0, 'description': u'不是您家设备喔,不能派币', 'payload': {}})
- payload = {
- 'orderNo': str(uuid.uuid1()),
- 'openId': customerOpenId,
- 'coins': coins,
- 'description': desc,
- 'groupId': groupId,
- 'groupName': group.groupName,
- 'address': group.address,
- 'ownerId': ownerId,
- 'operator': operator,
- 'result': 'success',
- 'via': 'sendcoin'
- }
- record = RechargeRecord(**payload)
- customer.recharge(RMB(0), RMB(coins))
- record.save()
- customer.account_recharge(record)
- if coins > VirtualCoin(0):
- try:
- task_caller(
- 'report_to_user_via_wechat', openId=customerOpenId,
- dealerId=str(request.user.bossId),
- templateName='refund_coins', **{
- 'title': u'尊敬的客户,已经退回%s金币到您的余额,您下次可以接着使用。祝您生活愉快。' % coins,
- 'backCount': u'金币:%s' % coins,
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- }
- )
- except Exception as e:
- logger.exception(e)
- return JsonResponse({'result': 1, 'description': None, 'payload': {}})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getModifyCustomerBalanceRecord(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 获取派币记录
- :param request:
- :return:
- """
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- customerOpenId = request.GET.get('id', None)
- user = MyUser.objects(openId=customerOpenId).first()
- if not user:
- records = RechargeRecord.objects(
- ownerId=str(request.user.bossId),
- via='sendcoin').order_by('-dateTimeAdded').skip((pageIndex - 1) * pageSize).limit(pageSize)
- else:
- records = RechargeRecord.objects(
- ownerId=str(request.user.bossId),
- openId=customerOpenId,
- via='sendcoin').order_by('-dateTimeAdded').skip((pageIndex - 1) * pageSize).limit(pageSize)
- dataList = []
- if not user:
- for r in records:
- u = MyUser.objects(openId=r.openId).first()
- if u is None:
- logger.error('invalid openId, openId=%s' % r.openId)
- continue
- dataList.append({
- 'name': u.nickname if u.nickname is not None else '',
- 'avatar': u.avatar,
- 'id': customerOpenId,
- 'remarks': r.my_description,
- 'operator': r.operator,
- 'coins': r.coins,
- 'groupName': r.groupName,
- 'createdTime': r.dateTimeAdded.strftime("%Y-%m-%d %H:%M:%S")
- })
- else:
- dataList = [
- {
- 'name': user.nickname if user.nickname is not None else '',
- 'avatar': user.avatar,
- 'id': customerOpenId,
- 'remarks': r.my_description,
- 'operator': r.operator,
- 'coins': r.coins,
- 'groupName': r.groupName,
- 'createdTime': r.dateTimeAdded.strftime("%Y-%m-%d %H:%M:%S")
- } for r in records
- ]
- count = records.count()
- if count <= pageSize:
- total = (pageIndex - 1) * pageSize + count
- else:
- total = (pageIndex - 1) * pageSize + 100
- return JsonResponse(
- {
- 'result': 1,
- 'description': None,
- 'payload':
- {
- 'dataList': paginate(dataList, pageIndex, pageSize),
- 'total': total,
- 'sendCoinsTotal': VirtualCoin(records.sum('coins'))
- }
- }
- )
- # 导出派币记录
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取派币记录失败"))
- @permission_required(ROLE.dealer)
- def reportModifyCustomerBalanceRecord(request):
- """
- 导出派币记录
- """
- dealer = request.user
- def get_offline_task_name(task_type, user, **kwargs):
- # type: (basestring, Dealer, Dict)->basestring
- tmp_list = [task_type, user.username]
- if 'logicalCode' in kwargs and kwargs['logicalCode']:
- tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],))
- if 'groupId' in kwargs and kwargs['groupId']:
- address = Group.get_group(kwargs['groupId']).get('address', '')
- tmp_list.append(u'地址_%s' % (address,))
- tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime']))
- tmp_list.append(str(utils_datetime.generate_timestamp_ex()))
- return '-'.join(tmp_list).replace("/", "_")
- query_dict = {
- 'startTime': request.GET.get('startTime', '') + ' 00:00:00',
- 'endTime': request.GET.get('endTime', '') + ' 23:59:59',
- 'pageIndex': int(request.GET.get('pageIndex', 1)),
- 'pageSize': int(request.GET.get('pageSize', 10)),
- 'customerOpenId': request.GET.get('id', None),
- "ownerId": str(request.user.bossId),
- }
- offline_task_name = get_offline_task_name(
- task_type=u'地址用户充值消费情况统计报表',
- user=dealer,
- **query_dict)
- file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name,
- process_func_name='export_modify_customer_balance_record_excel_from_db',
- task_type=OfflineTaskType.BUSINESS_REPORT,
- userid=str(dealer.id),
- role=ROLE.dealer)
- task_caller(func_name=offline_task.process_func_name,
- offline_task_id=str(offline_task.id),
- filepath=file_path,
- queryDict=query_dict)
- return JsonResponse({
- 'result': 1,
- 'description': u"请前往离线任务查看任务处理情况",
- 'payload': str(offline_task.id)})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getRefundRecord(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 获取退币记录
- :param request:
- :return:
- """
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- customerOpenId = request.GET.get('id', None)
- if not customerOpenId:
- return JsonErrorResponse(description=u'提交的用户id为空')
- user = MyUser.objects(openId=customerOpenId).first().to_dict()
- records = RechargeRecord.objects(ownerId=str(request.user.bossId), openId=customerOpenId, via='refund').order_by("-dateTimeAdded")
- dealer = Dealer.objects(id=str(request.user.bossId)).get()
- dataList = [
- {
- 'name': user['nickname'],
- 'avatar': user['avatar'],
- 'id': customerOpenId,
- 'description': r.my_description,
- 'operator': dealer.nickname,
- 'coins': r.coins,
- 'groupName': r.groupName,
- 'createdTime': r.dateTimeAdded.strftime("%Y-%m-%d %H:%M:%S")
- } for r in records
- ]
- total = records.count()
- return JsonResponse(
- {
- 'result': 1,
- 'description': None,
- 'payload':
- {
- 'dataList': paginate(dataList, pageIndex, pageSize),
- 'total': total,
- 'refundTotal': VirtualCoin(records.sum('coins'))
- }
- }
- )
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def payGateway(request):
- # type: (WSGIRequest)->JsonResponse
- current_user = request.user # type: Dealer
- try:
- # TODO # 此处流量卡传的是param 其他 加盟 api支付的都是传 params
- payload = json.loads(request.GET.get('param') or request.GET.get('params'))
- order_no = payload.get('orderNo')
- if not order_no:
- return JsonErrorResponse(u'参数错误,请刷新后再试')
- record = DealerRechargeRecord.objects(orderNo=order_no).first() # type: DealerRechargeRecord
- if not record:
- return JsonErrorResponse(u'订单不存在,请刷新后再试')
- payment_gateway = PaymentGateway.from_gateway_key(
- record.gateway,
- record.payGatewayKey,
- record.payAppType) # type: Optional[WechatPaymentGateway]
- logger.info('dealer wechat charge: gateway = %s; orderNo = %s, totalFee = %s' % (
- repr(payment_gateway), order_no, record.totalFee))
- OrderCacheMgr(record).initial()
- attach = {'dealerId': record.dealerId}
- body = record.get_body()
- # 转成以元为单位的钱,后面流程统一处理
- money = RMB(record.totalFee) * Decimal('0.01')
- if payment_gateway.pay_app_type == PayAppType.WECHAT:
- data = payment_gateway.generate_js_payment_params(
- payOpenId=payload.get('openId'),
- out_trade_no=order_no,
- notify_url=PAY_NOTIFY_URL.WECHAT_PAY_BACK,
- money=money,
- body=body,
- attach=attach)
- data.update({
- 'outTradeNo': record.orderNo, 'adShow': current_user.ad_show
- })
- response = JsonResponse({'result': 1, 'description': '', 'payload': data})
- else:
- raise Exception(cn(u'不支持该支付类型'))
- task_caller(func_name='poll_dealer_recharge_record',
- delay=PollRecordDefine.DELAY_BEFORE,
- expires=PollRecordDefine.TASK_EXPIRES,
- record_id=str(record.id),
- pay_app_type=payment_gateway.pay_app_type,
- interval=PollRecordDefine.WAIT_EACH_ROUND,
- total_count=PollRecordDefine.TOTAL_ROUNDS)
- return response
- except WeChatException as e:
- logger.exception(e)
- return JsonErrorResponse(description = e.tip)
- except Exception as e:
- logger.exception(e)
- return JsonErrorResponse(description=u'系统开小差了,请刷新后再试')
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getDeviceCardList(request):
- # type: (WSGIRequest)->JsonResponse
- def cmp_expire_time(x, y):
- if not x['simExpireDate']:
- return 1
- if not y['simExpireDate']:
- return -1
- if x['simExpireDate'] > y['simExpireDate']:
- return -1
- elif x['simExpireDate'] < y['simExpireDate']:
- return 1
- else:
- return 0
- searchKey = request.GET.get('searchKey', '')
- dealerId = str(request.user.bossId)
- agent = Agent.objects(id=request.user.agentId).first() # type: Optional[Agent]
- if not agent:
- logger.error('agent<id={}> is not exist.'.format(request.user.agentId))
- return JsonErrorResponse(description=u'系统错误')
- groupIds = Group.get_group_ids_of_dealer(dealerId)
- groupDict = Group.get_groups_by_group_ids(groupIds)
- devNoList = Device.get_devNos_by_group(groupIds)
- devices = Device.get_dev_by_nos(devNoList).values()
- annualTrafficCost = request.user.annualTrafficCost
- devList = []
- for dev in devices: # type: DeviceDict
- try:
- if searchKey in dev['groupNumber'] or searchKey in dev.devNo or searchKey in dev[
- 'remarks'] or searchKey in dev.logicalCode:
- group = groupDict.get(dev.groupId)
- if (settings.DEBUG and dev.logicalCode.startswith('DUMMY')) or dev.is_expired or dev.sim_expire_notify:
- item = {
- 'logicalCode': dev.logicalCode,
- 'devNo': dev.devNo,
- 'devTypeName': dev.devType['name'],
- 'groupName': group['groupName'],
- 'groupNumber': dev['groupNumber'],
- 'groupId': group['groupId'],
- 'simExpireDate': dev.fixedSimExpireDate,
- 'channelType': dev.channelType
- }
- devList.append(item)
- except Exception, e:
- logger.exception('[device]some error=%s' % e)
- continue
- devList.sort(cmp=cmp_expire_time)
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 100))
- items = devList[(pageIndex - 1) * pageSize:pageIndex * pageSize]
- devObjs = { obj.devNo: obj for obj in Device.objects.filter(devNo__in=[item['devNo'] for item in items])}
- for item in items:
- dev_obj = devObjs[item['devNo']] # type: Device
- trafficCardCost = dev_obj.trafficCardCost
- if not trafficCardCost:
- if request.user.trafficCardCost:
- trafficCardCost = request.user.trafficCardCost
- else:
- trafficCardCost = agent.trafficCardCost
- item['price'] = trafficCardCost if trafficCardCost > annualTrafficCost else annualTrafficCost
- items = sorted(items, key=lambda x:x['groupId'])
- return JsonResponse({
- 'result': 1,
- 'description': None,
- 'payload': {'page': pageIndex, 'total': len(devList), 'pageSize': pageSize, 'offset': 0,
- 'items': items}
- })
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getSimRechargeOrderList(request):
- # type: (WSGIRequest)->JsonResponse
- filterQuery = Q(
- __raw__ = {
- 'dealerId': str(request.user.bossId),
- 'product': {'$in': [DealerRechargeRecord.ProductType.SimCard, DealerRechargeRecord.ProductType.AutoSimCard]}
- })
- status = request.GET.get('status', None)
- if status:
- filterQuery &= Q(__raw__={'status': status})
- else:
- filterQuery &= Q(
- __raw__={'status': {'$nin': [DealerRechargeRecord.PayState.Cancel, DealerRechargeRecord.PayState.Close]}})
- searchKey = request.GET.get('searchKey', '')
- if searchKey:
- pattern = Regex.from_native(re.compile('.*' + searchKey + '.*'))
- filterQuery &= (Q(__raw__={'items': {'$elemMatch': {'name': {'$regex': pattern}}}}) | Q(
- __raw__={'orderNo': {"$regex": pattern}}))
- records = DealerRechargeRecord.objects(
- __raw__=filterQuery.to_query(DealerRechargeRecord)).order_by("-createdTime")
- items = []
- for record in records: # type: DealerRechargeRecord
- item = {
- 'name': record.name,
- 'totalFee': str(RMB(float(record['totalFee']) / 100)),
- 'orderNo': record.orderNo,
- 'status': record.status,
- 'createdTime': record.createdTime,
- 'finishedTime': record.finishedTime
- }
- items.append(item)
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- return JsonResponse({
- 'result': 1,
- 'description': '',
- 'payload': {
- 'page': pageIndex, 'total': len(items), 'pageSize': pageSize, 'offset': 0,
- 'items': items[(pageIndex - 1) * pageSize:pageIndex * pageSize]
- }
- })
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def createSimRechargeOrder(request):
- # type: (WSGIRequest)->JsonResponse
- current_user = request.user # type: Dealer
- devNoList = set(request.POST.getlist('list[]'))
- payment_gateway = get_inhourse_wechat_env_pay_gateway(
- ROLE.dealer) # type: Union[WechatPaymentGateway]
- record = create_dealer_sim_charge_order(payment_gateway, current_user, devNoList)
- if record:
- return JsonResponse({'result': 1, 'description': u'创建订单成功', 'payload': record.orderNo})
- else:
- return JsonErrorResponse(u'创建订单异常失败')
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def cancelSimRechargeOrder(request):
- # type: (WSGIRequest)->JsonResponse
- try:
- payload = json.loads(request.body) if request.body else {}
- if not payload:
- return JsonErrorResponse(description=u'数据不完整,请重试')
- order_no = payload['orderNo']
- order = DealerRechargeRecord.objects(orderNo=order_no).first() # type: DealerRechargeRecord
- if not order:
- return JsonErrorResponse(u'订单不存在,请刷新后再试')
- if not order.is_unpay:
- return JsonErrorResponse(u'订单已经处理,无法取消')
- if order.cancel():
- return JsonOkResponse('ok')
- else:
- return JsonErrorResponse(u'订单已经处理,无法取消')
- except Exception as e:
- logger.exception('unable to cancel dealer order, error=%s' % (e,))
- return JsonErrorResponse(description=u"系统错误")
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getSimRechargeOrderDetail(request):
- # type: (WSGIRequest)->JsonResponse
- try:
- orderNo = request.GET.get('orderNo')
- order = DealerRechargeRecord.objects(orderNo = orderNo).first() # type: DealerRechargeRecord
- if not order:
- return JsonErrorResponse(u'订单不存在,请刷新后再试')
- else:
- return JsonResponse({'result': 1, 'description': '', 'payload':
- {
- 'orderNo': order.orderNo,
- 'totalFee': '%.02f' % (float(order.totalFee) / 100),
- 'status': order.status,
- 'createdTime': order.createdTime,
- 'items': order.items
- }})
- except Exception as e:
- logger.exception('get dealer pay order list failure, error = %s' % (e,))
- return JsonErrorResponse(description = u'查询订单失败')
- @error_tolerate(nil=DefaultJsonErrorResponse)
- def getOwnerAgents(request):
- try:
- username = request.GET.get('username')
- managerId = request.GET.get('managerId')
- logger.debug('getOwnerAgents: username = %s; managerId = %s' % (username, managerId))
- agents = [str(a.id) for a in Agent.objects(managerId=str(managerId)).all()]
- items = []
- dealers = Dealer.get_collection().find({'username': username, 'agentId': {'$in': agents}})
- for dealer in dealers:
- agentId = dealer['agentId']
- agent = Agent.get_agent(agentId)
- item = {
- 'agentId': agentId,
- 'userHeadImg': agent['avatar'],
- 'agentLogoUrl': agent['productLogo'],
- 'agentBrandName': agent['productName'],
- 'displayName': agent['productName']
- }
- items.append(item)
- return JsonResponse({
- 'result': 1,
- 'description': None,
- 'payload': {'total': len(items),
- 'items': items}
- })
- except Exception as e:
- logger.exception('get dealer owner agents failure, error = %s' % (e,))
- return JsonErrorResponse(description=u'网络错误,请刷新后再试')
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getEquipmentTotal(request):
- # type: (WSGIRequest)->JsonResponse
- dealerId = str(request.user.bossId)
- groupIds = Group.get_group_ids_of_dealer(dealerId)
- devNoList = Device.get_devNos_by_group(groupIds)
- return JsonResponse({'result': 1, 'description': '', 'payload': len(devNoList)})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'设备类型不支持'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getPackageList(request):
- # type: (WSGIRequest)->JsonResponse
- devTypeId = request.GET.get('typeId', None)
- if not devTypeId:
- return JsonResponse({'result': 0, 'description': u'设备类型为空', 'payload': {}})
- dealer = request.user.myBoss # type: Dealer
- devType = DeviceType.objects.filter(id=str(devTypeId)).first() # type: DeviceType
- if devType['code'] in support_policy_weifule + support_policy_device:
- isTemp = request.GET.get('isTemp', None) == 'true'
- from apps.web.core.models import DriverAdapter
- adapter = DriverAdapter.get_driver_adapter(devType['code'], None)
- if adapter.support_device_package:
- payload = adapter.get_reg_model(dealer, devTypeId, isTemp=isTemp)
- return JsonResponse({'result': 1, 'description': None, 'payload': payload})
- dataList = {}
- if devTypeId in dealer.defaultWashConfig:
- dataList = dealer.defaultWashConfig[devTypeId]
- if not dataList:
- dataList = DeviceType.objects(id=str(devTypeId)).get().package
- no_unit_list = filter(lambda x: x.get("unit") == None, dataList)
- if len(no_unit_list) == len(dataList):
- datalist = map(lambda x: (x.update({"unit": "分钟"}), x)[1], dataList)
- displaySwitchs = {}
- if hasattr(devType, "displayPriceSwitch"):
- displaySwitchs.update({"displayPriceSwitch": devType.displayPriceSwitch})
- if hasattr(devType, "displayCoinsSwitch"):
- displaySwitchs.update({"displayCoinsSwitch": devType.displayCoinsSwitch})
- if hasattr(devType, "displayTimeSwitch"):
- displaySwitchs.update({"displayTimeSwitch": devType.displayTimeSwitch})
- if hasattr(devType, "setPulseAble"):
- displaySwitchs.update({"setPulseAble": devType.setPulseAble})
- if hasattr(devType, "setBasePriceAble"):
- displaySwitchs.update({"setBasePriceAble": devType.setBasePriceAble})
- if devType['code'] in [Const.DEVICE_TYPE_CODE_CAR_CHANGING_JINQUE, Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_JFPG,Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_DOUB_JFPG]:
- displaySwitchs = {
- 'displayPriceSwitch': True,
- 'displayCoinsSwitch': False,
- 'displayTimeSwitch': False,
- 'setPulseAble': False,
- 'setBasePriceAble': False,
- }
- return JsonResponse({'result': 1, 'description': None, 'payload': {'ruleList':dataList, 'displaySwitchs':displaySwitchs}})
- # ## 经销商绑定微信(为了接受微信推送)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getDealerBindWechatSMSCode(request):
- # type: (WSGIRequest)->JsonResponse
- """
- :param request:
- :return:
- """
- try:
- phoneNumber = request.user.username
- agent = Agent.get_agent(request.user.agentId)
- productName = agent['productName']
- if not phoneNumber:
- return JsonResponse({'result': 0, 'description': u'手机号码为空'})
- status, msg = dealerBindWechatSMSProvider.get(phoneNumber=phoneNumber,
- productName=productName,
- vendor=SysParas.get_sms_vendor(request.user.smsVendor))
- if not status:
- return JsonResponse({'result': 0, 'description': msg})
- else:
- return JsonResponse({'result': 1, 'description': ''})
- except Exception, e:
- logger.exception('unable to get %s' % e)
- return JsonResponse({'result': 0, 'description': ''})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def verifyNewWechatBinding(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 跳转到微信授权页面绑定
- :param request:
- :return:
- """
- currentDealer = request.user # type: cast(Dealer)
- code = request.POST.get('code')
- if not code:
- return JsonErrorResponse(description=u'code未提供')
- status, msg = dealerBindWechatSMSProvider.verify(phoneNumber=request.user.username, smsCode=code)
- if not status:
- return JsonErrorResponse(description=msg)
- auth_bridge = get_wechat_auth_bridge(source=currentDealer, app_type=APP_TYPE.WECHAT_MANAGER)
- return JsonResponse(
- {
- 'result': 1,
- 'description': None,
- 'payload': {
- 'redirect_uri': auth_bridge.generate_auth_url_user_scope(
- redirect_uri=DEALER_BIND_WECHAT_URL)
- }
- })
- @error_tolerate(logger=logger, nil=DealerBindIdResponseRedirect(result='error'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def verifyNewWechatBindingCallback(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 绑定后台openId
- TODO: 加入变更记录
- :param request:
- :return:
- """
- auth_code = request.GET.get('code')
- if not auth_code:
- return JsonErrorResponse(description=u'未收到code,请刷新重试')
- currentDealer = request.user # type: cast(Dealer)
- auth_bridge = get_wechat_auth_bridge(source=currentDealer, app_type=APP_TYPE.WECHAT_MANAGER)
- user_info = auth_bridge.get_user_info(auth_code=auth_code)
- user_info_payload = {
- 'avatar': user_info['avatar'],
- 'country': user_info['country'],
- 'province': user_info['province'],
- 'city': user_info['city'],
- 'sex': user_info['sex'],
- 'nickname': user_info['nickname']
- }
- logger.debug('dealer(id=%s) is binding wechat for messaging, bridge=%s' % (str(request.user.bossId), auth_bridge))
- dealerWechatBindingUpdated = request.user.update(
- managerialAppId=auth_bridge.app.appid,
- managerialOpenId=user_info['openId'],
- wechatAuthUserInfo=user_info_payload,
- managerialWechatBoundTime=datetime.datetime.now())
- if dealerWechatBindingUpdated:
- return DealerBindIdResponseRedirect(result='ok')
- else:
- return DealerBindIdResponseRedirect(result='error')
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getBoundWechat(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 获取绑定后台openId的用户信息
- :param request:
- :return:
- """
- ownerId = str(request.user.bossId)
- dealer = Dealer.objects(id=ownerId).get() # type: Dealer
- return JsonResponse(
- {
- "result": 1,
- "description": None,
- 'payload': {
- "bound": dealer.isManagerialOpenIdBound,
- "avatar": dealer.wechatAuthUserInfo.get('avatar'),
- "sex": dealer.wechatAuthUserInfo.get('sex'),
- "nickname": dealer.wechatAuthUserInfo.get('nickname')
- }
- })
- @permission_required(ROLE.dealer, ROLE.agent, ROLE.subaccount)
- def setAdShow(request):
- # type: (WSGIRequest)->JsonResponse
- try:
- payload = json.loads(request.body) if request.body else {}
- if not payload:
- return JsonErrorResponse(description=u'数据不完整,请重试')
- user = Dealer.objects.get(id=payload['id']) if 'id' in payload else request.user # type: Dealer
- adShow = payload.get('adShow', user.adShow)
- user.adShow = adShow
- user.save()
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- except DoesNotExist, e:
- logger.exception("dealer does not exist, error = %s" % e)
- return JsonResponse({"result": 0, "description": u'经销商不存在', 'payload': {}})
- except Exception, e:
- logger.exception("set adShow error = %s" % e)
- return JsonResponse({"result": 0, "description": u'系统错误', 'payload': {}})
- @permission_required(ROLE.manager)
- def getDealerDetailList(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 厂商获取经销商详情
- :param request:
- :return:
- """
- def count_devices(ownerId):
- devNoList = [device['devNo'] for device in
- Device.get_collection().find({'ownerId': ownerId, 'groupId': {'$ne': ''}}, {'devNo': 1, '_id': 0})]
- allCount = len(devNoList)
- devDict = Device.get_dev_by_nos(devNoList)
- if not devDict:
- return 0, 0, 0
- onlineCount = 0
- for devNo, dev in devDict.items():
- if dev["online"]:
- onlineCount += 1
- offlineCount = allCount - onlineCount
- return onlineCount, offlineCount, allCount
- mid = str(request.user.id)
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- agentId = request.GET.get('agentId', None)
- searchKey = request.GET.get('searchKey', None)
- dealers = Dealer.search(searchKey)
- agentMap = {str(agent.id): agent.username for agent in Agent.objects(managerId=mid)}
- agentIds = agentMap.keys()
- if agentId:
- dealers = dealers.filter(agentId=agentId)
- elif agentIds:
- dealers = dealers.filter(agentId__in=agentIds)
- total = dealers.count()
- dealers_per_page = dealers.skip((pageIndex - 1) * pageSize).limit(pageSize)
- dataList = []
- for d in dealers_per_page:
- report = Accounting.getOwnerIncome(str(d.id), now=datetime.datetime.now())
- onlineCount, offlineCount, allCount = count_devices(str(d.id))
- hasZJFirePlatform = True
- ZJFirePlatform = {}
- try:
- obj = Company.objects.get(ownerId=str(d.id))
- ZJFirePlatform = {
- 'companyName': obj.name,
- 'companyCode': obj.code,
- 'companyAddress': obj.address,
- 'contactsName': obj.contactName,
- 'contactsTel': obj.telephone,
- 'deviceManufacturer': obj.manufacturer
- }
- hasZJFirePlatform = True
- except Exception, e:
- pass
- now = datetime.datetime.now()
- today = now.strftime(Const.DATE_FMT)
- rcds = DealerDailyStat.get_collection().find({'dealerId':ObjectId(d.id), 'date':today}, {'daily':1, 'activedDevRatio':1})
- if rcds.count() == 0:
- todayIncome = 0
- todayRechargeIncome = 0
- todayChargeCardIncome = 0
- else:
- info = rcds[0]
- todayIncome = info.get('daily', {}).get('totalIncome', 0)
- income = info.get('daily', {}).get('income', {})
- todayRechargeIncome = income.get('recharge', 0)
- todayChargeCardIncome = RMB(income.get('chargeCard', 0)) + RMB(income.get('virtualChargeCard', 0))
- monthDay = MONTH_DATE_KEY.format(year=now.year, month=now.month)
- rcds = DealerMonthlyStat.get_collection().find({'dealerId':ObjectId(d.id), 'date':monthDay}, {'addedUserCount':1})
- if rcds.count() == 0:
- userCountAddedThisMonth = 0
- else:
- info = rcds[0]
- userCountAddedThisMonth = rcds[0].get('addedUserCount', 0)
- detail = d.to_dict()
- dataList.append({
- 'id': str(d.id),
- 'name': d.nickname,
- 'tel': d.username,
- 'agentInfo': agentMap.get(detail['agentId'], ''),
- 'dateTimeAdded': d.dateTimeAdded,
- 'lineCoins': report['lineCoins'],
- 'payIncome': todayIncome,
- 'todayRechargeIncome': todayRechargeIncome,
- 'todayChargeCardIncome': todayChargeCardIncome,
- 'userCount':d.userCount,
- 'userCountAddedThisMonth':userCountAddedThisMonth,
- 'devTotalNum': allCount,
- 'offlineTotal': offlineCount,
- 'onlineTotal': onlineCount,
- 'detail': json_dumps(detail),
- 'ZJFirePlatform': ZJFirePlatform,
- 'hasZJFirePlatform': hasZJFirePlatform,
- 'disableDevice': True if "dealerDisableDevice" in d.features else False
- })
- return JsonResponse({
- 'result': 1,
- 'description': '',
- 'payload': {
- 'total': total,
- 'dataList': dataList
- }
- })
- @permission_required(ROLE.manager)
- def getDealerListByAgent(request):
- # type: (WSGIRequest)->JsonResponse
- """
- :param request:
- :return:
- """
- agentIds = json.loads(request.body).get('agentIds', [])
- agents = {str(_.id): _.nickname for _ in Agent.objects(id__in=agentIds)}
- if not agents: return JsonResponse({'result': 1, 'payload': []})
- dataList = [
- {
- 'dealerName': _.nickname,
- 'dealerId': str(_.id),
- 'agentId': str(_.agentId),
- 'agentName': agents[str(_.agentId)]
- }
- for _ in Dealer.objects(agentId__in=agentIds)
- ]
- return JsonResponse({'result': 1, 'payload': {'dataList': dataList, 'total': len(dataList)}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取设备列表失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def equipmentList(request):
- # type: (WSGIRequest)->JsonResponse
- def _get_port_status(portDict):
- allPorts = portDict.get("allPorts", 0)
- usedPorts = portDict.get("usedPorts", 0)
- usePorts = portDict.get("usePorts", 0)
- return allPorts, usedPorts, usePorts
- dealerId = str(request.user.bossId)
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- equipmentGroupId = request.GET.get('equipmentGroupId')
- online = request.GET.get('online')
- searchKey = request.GET.get('searchKey', '')
- sort = request.GET.get('sort', 'logicalCode')
- partnerGroupList = Group.get_group_ids_of_partner(dealerId)
- ownGroupList = Group.get_group_ids_of_dealer(dealerId)
- groupIds = partnerGroupList + ownGroupList
- if not equipmentGroupId:
- selectedGroupIds = groupIds
- else:
- selectedGroupIds = [equipmentGroupId]
- if not online:
- onlineStates = [0, 1]
- else:
- onlineStates = [int(online)]
- groupDict = Group.get_groups_by_group_ids(selectedGroupIds)
- devNoList = Device.get_devNos_by_group(selectedGroupIds)
- devs = Device.get_dev_by_nos(devNoList).values()
- devDict, deviceCount = {}, 0
- devCacheMap = Device.get_many_dev_control_cache(devNoList)
- showPortStatus = bool(request.user.feature_boolean_map.get("showPortStatus", None))
- for dev in devs: # type: DeviceDict
- if dev.online not in onlineStates:
- continue
- group = groupDict.get(dev['groupId'])
- if group is None:
- continue
- if any(map(lambda _: searchKey in _, (dev['devNo'],
- dev['remarks'],
- dev['logicalCode'],
- group['groupName'],
- group['address']))):
- isFault = dev.get('isFault', False)
- isDND = dev.is_DND_now
- item = {
- 'id': dev.devNo,
- 'logicalCode': dev.logicalCode,
- 'name': group['groupName'],
- 'groupId': group['groupId'],
- 'type': dev.devType['name'],
- 'typeId': dev.devType['id'],
- 'devType': dev.devType,
- 'unit': dev.devType.get('unit', DeviceType.unit.default),
- 'online': dev.online,
- 'signal': dev.signal,
- 'timeBased': dev.devType.get('timeBased', DeviceType.timeBased.default),
- 'autoRefundEnable': dev.devType.get('autoRefundEnable', DeviceType.autoRefundEnable.default),
- 'channelType': dev.channelType,
- 'isManager': False if dev['groupId'] in partnerGroupList else True,
- 'serviceState': dev.get('serviceState', Const.ServiceState.Normal.name),
- 'remarks': dev.get('remarks', Device.remarks.default),
- 'status': dev.status,
- 'statusInfo': dev.statusInfo,
- 'isFault': isFault,
- 'isDND': isDND,
- 'offTimeDate': datetime.datetime.fromtimestamp(int(str(dev.offTime)[0:10])).strftime('%Y-%m-%d %H:%M:%S') if dev.offTime is not None else '',
- 'tag': group.get("tag", ""),
- "deviceWarning": dev.is_warning
- }
- # 最近离线时间小于2017年的都为空
- offTimeYear = int(item['offTimeDate'][0:4])
- if offTimeYear < 2017:
- item['offTimeDate'] = ''
- if showPortStatus:
- # 这个地方需要添加 具体的端口 使用情况 故障、工作、空闲等 使用情况从缓存中直接读取,如果不存在 则没有,不去具体查询设备
- devCache = devCacheMap.get(device_control_cache_key(dev["devNo"]), {})
- allPorts, usedPorts, usePorts = _get_port_status(devCache)
- hasPort = showPortStatus and bool(allPorts)
- item.update({"hasPort": hasPort})
- if hasPort: item.update(
- {"portStatus":
- {
- "all": allPorts,
- "idle": usePorts,
- "used": usedPorts,
- }
- }
- )
- else:
- item.update({"hasPort": False})
- if not dev.online and Device.utils_is_expired(dev):
- item.update({'simExpireDate': dev.formatSimExpireDate, 'simStatus': dev.simStatus})
- if dev['groupId'] in devDict:
- devDict[dev['groupId']].append(item)
- else:
- devDict[dev['groupId']] = [item]
- # 近7日平均使用率
- if dev.devType.get('features', {}).get('7_days_average_utilization_rate', False) is True:
- nowDateTime = datetime.datetime.now()
- sevenDaysAgoDateTime = nowDateTime - datetime.timedelta(days=7)
- consumeRecords = ConsumeRecord.objects(devNo=dev.devNo, dateTimeAdded__gte=sevenDaysAgoDateTime, dateTimeAdded__lte=nowDateTime)
- sevenDaysAverage = round(((float(consumeRecords.count()) / 7) / 10) * 100, 2)
- item.update({'sevenDaysAverage': sevenDaysAverage})
- deviceCount += 1
- showGroups = paginate(sorted(devDict.keys(), reverse=False), pageSize=pageSize, pageIndex=pageIndex)
- devList = []
- for keyGrp in showGroups:
- devList.extend(devDict[keyGrp])
- if sort == 'logicalCode':
- tempList = natural_sort(array=devList, key='logicalCode', reverse=False)
- elif sort == 'devType':
- tempList = sorted(devList, key=lambda x: x['devType']['name'])
- elif sort == 'remarks':
- tempList = sorted(devList, key=lambda x: x['remarks'], reverse=True)
- elif sort == "tag":
- tempList = devList
- else:
- raise InvalidParameter(u'搜索条件不合法')
- if sort == "tag":
- devList = sorted(tempList, key=lambda x: x['tag'], reverse=True)
- else:
- devList = sorted(tempList, key=lambda x: x['groupId'])
- return JsonResponse({
- "result": 1,
- "description": None,
- 'payload': {
- "total": deviceCount,
- "groupCount": len(devDict.keys()),
- "dataList": devList
- }
- })
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取库存列表失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def equipmentListForStock(request):
- # type: (WSGIRequest)->JsonResponse
- ownerId = str(request.user.bossId)
- equipmentGroupId = request.GET.get('equipmentGroupId', 'all')
- online = request.GET.get('online', 'all')
- searchKey = request.GET.get('searchKey', '')
- groupIds, devTempList = Device.filter(dealerId=ownerId, searchKey=searchKey, online=online,
- equipmentGroupId=equipmentGroupId)
- devList = []
- for dev in devTempList:
- if not dev.has_key('quantity'):
- continue
- devList.append(dev)
- return JsonResponse({
- "result": 1,
- "description": None,
- 'payload': {
- "total": len(groupIds),
- "groupCount": len(devList),
- "dataList": devList
- }
- })
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'解绑失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- @request_limit_by_user(operation='unbindDevice', limit=100, logger=logger)
- def unbindDevice(request):
- def unbindDeviceDefault(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 经销商解绑设备
- ..modified 去掉对代理商串货的限制
- :param request:
- :return:
- """
- owner_id = str(request.user.bossId)
- devNo = request.POST.get('value', None)
- if devNo is None:
- return JsonResponse({"result": 0, "description": u"缺少参数", 'payload': {}})
- dev = Device.get_dev(devNo) # type: DeviceDict
- devType = dev['devType']
- groupId = dev['groupId']
- if dev is None:
- return JsonResponse({"result": 0, "description": u"该设备不存在,请刷新后再试", 'payload': {}})
- if not dev.is_registered:
- return JsonResponse({"result": 0, "description": u"该设备没有注册,不需要解绑", 'payload': {}})
- if dev.ownerId != owner_id:
- return JsonResponse({"result": 0, "description": u"不是您的设备,不能够解绑", 'payload': {}})
- try:
- Device.un_register(dev=dev, operator=request.user.human_id)
- dealer = Dealer.objects.get(id=owner_id)
- dealer.devCount -= 1
- dealer.save()
-
- except RentDeviceError as rde:
- return JsonErrorResponse(rde.message)
- except Exception as e:
- logger.exception(
- 'un register failure. error = %s, devNo = %s, ownerId = %s' % (e, devNo, str(request.user.bossId)))
- return JsonResponse({"result": 0, "description": u"系统错误", 'payload': {}})
-
- group = Group.get_group(groupId)
- if group.get('swapFlag', False):
- agentId = request.user.agentId
- agent = Agent.objects(id=agentId).first()
- if agent:
- devNum = 0
- if 'majorDeviceType' in devType and (u'直流' in devType['majorDeviceType'] or u'交流' in devType['majorDeviceType']):
- devNum = -1
- SwapGroup.update_swap_time_and_num(groupId, devNum)
- SwapContract.update_swap_time_and_num(groupId, owner_id, agentId, agent.managerId, devNum)
-
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
-
- current_user = request.user # type: UserSearchable
- if not current_user.normal:
- return JsonResponse({"result": 0, "description": u"账号异常,不能进行该操作", 'payload': {}})
- return unbindDeviceDefault(request)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'解绑失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- @request_limit_by_user(operation='unbindAllNode', limit=100, logger=logger)
- def unbindAllNode(request):
- # 获取主机的子节点
- lc = request.POST.get('logicalCode', None)
- master = Device.get_dev_by_l(lc) # type: DeviceDict
- nodeList = master.deviceAdapter.get_node_list()
- if not nodeList:
- return JsonResponse({"result": 0, "description": u"该设备不存在,请刷新后再试", 'payload': {}})
- owner_id = str(request.user.bossId)
- # TODO 和刘崇确认 此处先简单修复 然后后续可能进行优化
- # 进行检查 保证所有设备都是 该经销商的
- errDevs = list()
- for node in nodeList: # type: DeviceDict
- if not node.is_registered:
- continue
- if node.ownerId != owner_id:
- errDevs.append(node.logicalCode)
- if errDevs:
- return JsonErrorResponse(description=u"设备{} 不是您的设备 无法解绑".format(" ".join(errDevs)))
- # 再解除经销商绑定
- for node in nodeList:
- if not node.is_registered:
- continue
- Device.un_register(dev=node, operator=request.user.human_id)
- dealer = Dealer.objects.get(id=owner_id)
- dealer.devCount -= 1
- dealer.save()
- return JsonOkResponse()
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'删除套餐失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def delPackages(request):
- # type: (WSGIRequest)->JsonResponse
- curr_user = request.user # type: Union[Dealer, SubAccount]
- if not curr_user.normal:
- return JsonErrorResponse(description=u'账号异常,不能进行该操作')
- devNo = request.POST.get('devNo', None)
- ruleId = request.POST.get('ruleId', None)
- if devNo is None or ruleId is None:
- return JsonResponse({"result": 0, "description": u"缺少参数", 'payload': {}})
- dev = Device.get_dev(devNo)
- if dev is None:
- return JsonResponse({"result": 0, "description": u"找不到设备", 'payload': {}})
- try:
- dev['washConfig'].pop(ruleId)
- except Exception, e:
- logger.exception('pop washconfig error=%s,ruleId=%s,devNo=%s' % (e, ruleId, devNo))
- return JsonResponse({"result": 0, "description": u'该套餐已经被删除了,请刷新页面', 'payload': {}})
- try:
- Device.get_collection().update_one({'devNo': devNo}, {'$set': {'washConfig': dev['washConfig']}})
- Device.invalid_device_cache(devNo)
- except Exception, e:
- logger.exception('update device washconfig error=%s,devNo=%s,washConfig=%s' % (e, devNo, dev['washConfig']))
- return JsonResponse({"result": 0, "description": u'保存套餐出错,请稍候再试', 'payload': {}})
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取套餐失败'))
- @permission_required(ROLE.dealer, ROLE.agent, ROLE.subaccount)
- def getPackages(request):
- # type: (WSGIRequest)->JsonResponse
- lc = request.GET.get('logicalCode', None)
- dev = Device.get_dev_by_l(lc) # type: DeviceDict
- if dev is None:
- return JsonErrorResponse(description=u"找不到设备")
- maxCoins = dev.get('maxCoins', 4)
- devNo = dev.devNo
- # 设备没注册, 走脉冲测试
- if not dev.ownerId:
- devData = {
- 'id': devNo,
- 'maxCoins': maxCoins,
- 'devNo': devNo,
- 'type': u'脉冲',
- 'typeCode': u'201',
- 'groupName': u'测试',
- 'groupNumber': 666
- }
- defaultWashconfig = {'1': {'coins': 1}, '2': {'coins': 2}, '3': {'coins': 3}, '4': {'coins': 4},
- '5': {'coins': 5}}
- ruleList = [
- {
- 'id': packageId,
- 'name': u'测试',
- 'coins': rule['coins'],
- 'price': rule.get('price', rule['coins'])
- } for packageId, rule in defaultWashconfig.items()
- ]
- return JsonResponse({"result": 1, "description": None, 'payload': {'devData': devData, 'ruleList': ruleList}})
- group = Group.get_group(dev['groupId'])
- if group is None:
- return JsonErrorResponse(description=u'找不到设备')
- if group['ownerId'] != str(request.user.bossId):
- return JsonErrorResponse(description=u'找不到设备')
- devData = {
- 'id': devNo,
- 'maxCoins': maxCoins,
- 'isManager': True,
- 'groupName': group['groupName'],
- 'groupNumber': dev['groupNumber'],
- 'devNo': devNo,
- 'type': dev['devType']['name'],
- 'typeCode': dev['devType']['code']
- }
- if "displaySwitchs" in dev["otherConf"]:
- displaySwitchs = dev["otherConf"].get('displaySwitchs')
- else:
- displaySwitchs = {'displayCoinsSwitch': True,
- 'displayTimeSwitch': True,
- 'displayPriceSwitch': True,
- "setPulseAble": False,
- "setBasePriceAble": False}
- if dev.channelType != DeviceChannelType.Channel_BT:
- smartBox = ActionDeviceBuilder.create_action_device(dev)
- try:
- portDict = smartBox.dealer_get_port_status()
- if portDict:
- chargeIndex = {}
- for index, info in portDict.items():
- if "status" not in info:
- continue
- if info['status'] == Const.DEV_WORK_STATUS_IDLE:
- chargeIndex[index] = 'idle'
- elif info['status'] == Const.DEV_WORK_STATUS_WORKING:
- chargeIndex[index] = 'busy'
- elif info['status'] == Const.DEV_WORK_STATUS_FAULT:
- chargeIndex[index] = 'fault'
- elif info['status'] == Const.DEV_WORK_STATUS_FORBIDDEN:
- chargeIndex[index] = 'ban'
- elif info['status'] == Const.DEV_WORK_STATUS_CONNECTED:
- chargeIndex[index] = 'connected'
- elif info['status'] == Const.DEV_WORK_STATUS_FINISHED:
- chargeIndex[index] = 'finished'
- devData.update({'chargeIndex': chargeIndex})
- except ServiceException, e:
- return JsonErrorResponse(description=e.result.get('description'))
- except Exception as e:
- logger.exception(e)
- return JsonErrorResponse(description=u'未知错误')
- if dev["devType"]["code"] == Const.DEVICE_TYPE_CODE_HP_GATE:
- if request.GET.get("isRemoteUpper", None):
- ruleList = []
- else:
- tempList = sorted(dev["washConfig"].get("1", {}).items(), key=lambda x: x[0])
- ruleList = [v for _, v in tempList]
- chargeIndex = {}
- if dev["otherConf"].get("controlEnter") in ("1", "2"):
- chargeIndex["enter"] = "idle"
- if dev["otherConf"].get("controlExit") in ("1", "2"):
- chargeIndex["exit"] = "idle"
- devData.update({'chargeIndex': chargeIndex})
- if request.GET.get("isRemoteUpper", None):
- ruleList = []
- elif dev["devType"]["code"] in support_policy_weifule:
- if dev.deviceAdapter.support_device_package:
- payload = dev.deviceAdapter.dealer_show_package()
- payload.update({"devData": devData})
- return JsonOkResponse(payload=payload)
- elif dev["devType"]["code"] in support_policy_device:
- if dev.deviceAdapter.support_device_package:
- payload = dev.deviceAdapter.dealer_show_package()
- payload.update({"devData": devData})
- return JsonOkResponse(payload=payload)
- elif dev["devType"]["code"] in [Const.DEVICE_TYPE_CODE_CAR_CHANGING_JINQUE, Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_JFPG, Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_DOUB_JFPG, Const.DEVICE_TYPE_CODE_CHARGE_XIAOKEDOU]:
- if dev.deviceAdapter.support_device_package:
- payload = dev.deviceAdapter.dealer_show_package()
- payload.update({"devData": devData})
- return JsonOkResponse(payload=payload)
- else:
- snRuleList = []
- ruleList = []
- for packageId, rule in dev['washConfig'].items():
- item = {
- 'id': packageId,
- 'name': rule['name'],
- 'coins': rule['coins'],
- 'price': rule.get('price', rule['coins']),
- 'time': rule.get('time', 20),
- 'description': rule.get('description', ''),
- 'imgList': rule.get('imgList', []),
- 'unit': rule.get('unit', u'分钟'),
- 'switch': rule.get('switch', True),
- }
- if rule.get('pulse'):
- item.update({
- 'pulse': rule.get('pulse'),
- })
- if rule.get('basePrice'):
- item.update({
- 'basePrice': rule.get('basePrice'),
- })
- if rule.get('billingMethod') and rule['billingMethod'] != CONSUMETYPE.BILL_AS_SERVICE:
- item.update({
- 'billingMethod': rule['billingMethod'],
- })
- if 'sn' in rule:
- item['sn'] = rule['sn']
- ruleList.append(item)
- ruleList = sorted(ruleList, key=lambda x: (x.get('sn'), x.get('id')))
- payload = {"devData": devData, "ruleList": ruleList, 'displaySwitchs': displaySwitchs}
- unit_price = dev.otherConf.get('unit_price', {})
- if dev.devTypeCode in [Const.DEVICE_TYPE_CODE_CHANGING_WEIFULE2]:
- try:
- if not unit_price:
- dev.deviceAdapter.set_dev_setting(dev.deviceAdapter.get_dev_setting())
- unit_price = Device.get_dev_by_l(lc).otherConf.get('unit_price', {})
- except:
- pass
- if unit_price:
- payload.update({'unit_price': unit_price})
- return JsonOkResponse(payload=payload)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'保存套餐失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def savePackages(request):
- """
- 保存套餐
- :param request:
- :return:
- """
- # 检测套餐单位一致性校验
- def check_package_unit(typeCode, package):
- # 电川汽车装有按金额启动,电量启动和充满自停的需求
- if typeCode == Const.DEVICE_TYPE_CODE_CHANGING_DIANCHUANCARCHARGING:
- return True
- if typeCode in skip_package_unit_verify_list:
- return True
- dic = map(lambda x: {'unit': x.get('unit') }, package)
- res = reduce(lambda x, y: x if x == y else None, dic)
- if res is None:
- return False
- else:
- return True
- # 检查套餐单位单位小数点后两位校验
- def check_params_range(typeCode, package):
- if typeCode in skip_package_range_verify_list:
- return None
- dic = map(lambda x: [x.get('time')], package)
- res = reduce(lambda x, y: x + y, dic)
- result = None
- for item in res:
- l = str(item).split(".")
- if len(l) > 1 and len(l[1]) > 2:
- result = (res.index(item) // 3) + 1
- break
- return result
- # 套餐参数完整性校验
- def check_params(typeCode, package):
- if typeCode in skip_package_params_verify_list:
- return True
- lis = map(lambda x: [x.get('time'), x.get('price'), x.get('coins')], package)
- res = reduce(lambda x, y: x + y, lis)
- for i in res:
- if i is None or float(i) < 0:
- return False
- return True
- # 套餐和金币是否需要强制1:1
- def check_price_equal_coin(_devDict, _package):
- for _dev in _devDict.values():
- # 非出租设备 不影响
- if not _dev.isRent:
- continue
- for _rule in _package:
- if RMB(_rule["price"]) != RMB(_rule["coins"]):
- return False
- return True
- curr_user = request.user # type: Union[Dealer, SubAccount]
- if not curr_user.normal:
- return JsonErrorResponse(description=u'账号异常,不能进行该操作')
- status, msg = ensure_all_fields_are_not_empty(
- {k: v for k, v in request.POST.items() if k not in ('ruleId',)})
- if not status:
- return JsonErrorResponse(description=msg)
- paras = json.loads(request.body) if request.body else {}
- if not paras:
- return JsonErrorResponse(description=u'提交数据为空')
- if paras['logicalCode'].__class__.__name__ == 'list':
- devNoList = [Device.get_devNo_by_logicalCode(lc) for lc in paras['logicalCode']]
- else:
- devNoList = [Device.get_devNo_by_logicalCode(paras['logicalCode'])]
- devDict = Device.get_dev_by_nos(devNoList)
- if not devDict:
- return JsonErrorResponse(description=u'找不到设备')
- typeCode = devDict.values()[0]['devType']['code']
- if typeCode in support_policy_weifule:
- dev = devDict.values()[0]
- if dev.deviceAdapter.support_device_package:
- try:
- dev.deviceAdapter.format_device_package(**paras)
- except ServiceException as e:
- return JsonResponse({"result": 0, "description": e.result['description'], 'payload': {}})
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- elif typeCode in support_policy_device:
- dev = devDict.values()[0]
- if dev.deviceAdapter.support_device_package:
- try:
- dev.deviceAdapter.format_device_package(**paras)
- except ServiceException as e:
- return JsonResponse({"result": 0, "description": e.result['description'], 'payload': {}})
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- # 解析washConfig,如果需要下发设备,解析出来setConfig
- serviceList = paras['serviceData']
- displaySwitchs = paras.get('displaySwitchs', {'displayCoinsSwitch': True,
- 'displayTimeSwitch': True,
- 'displayPriceSwitch': True,
- 'setPulseAble': False,
- 'setBasePriceAble': False})
- # 调整sn顺序
- for item in serviceList:
- item["sn"] = serviceList.index(item)
- if not check_params(typeCode, serviceList):
- return JsonErrorResponse(description=u'请完整的填写套餐中的所有参数')
- if not check_package_unit(typeCode, serviceList):
- return JsonErrorResponse(description=u'套餐用户获得参数单位配置需要一致')
- f = check_params_range(typeCode, serviceList)
- if f:
- return JsonErrorResponse(description=u'第%s个套餐 用户获得参数应为小数点后两位' % f)
- if not check_price_equal_coin(devDict, serviceList):
- return JsonErrorResponse(description=u"套餐金币与价格必须相等!")
- washConfig, setConfig = {}, {}
- agent = Agent.objects.get(id=request.user.agentId)
- existIds = []
- for rule in serviceList:
- if 'id' in rule:
- existIds.append(rule['id'])
- # 霍珀道闸 后付费模式 使用阶梯计费
- if typeCode == Const.DEVICE_TYPE_CODE_HP_GATE:
- rule = {str(index + 1): v for index, v in enumerate(serviceList)}
- washConfig = {"1": rule}
- elif typeCode in [Const.DEVICE_TYPE_CODE_CAR_CHANGING_JINQUE,Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_JFPG, Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_DOUB_JFPG, Const.DEVICE_TYPE_CODE_CHARGE_XIAOKEDOU]:
- dev = devDict.values()[0]
- if dev.deviceAdapter.support_device_package:
- try:
- washConfig, displaySwitchs = dev.deviceAdapter.format_device_package(**paras)
- except ServiceException as e:
- return JsonResponse({"result": 0, "description": e.result['description'], 'payload': {}})
- else:
- for rule in serviceList:
- if rule.has_key('coins') and rule.has_key('price'):
- if not (is_number(rule['coins']) and is_number(rule['price']) and is_number(
- rule.get('time', 0))):
- return JsonErrorResponse(description=u'金币数目或者时间或者价格必须是数字')
- else:
- rule['coins'], rule['price'] = 0, 0 # 对于那种先不需要付费的,这个就直接是0
- if RMB(rule['price']) >= request.user.maxPackagePrice:
- return JsonErrorResponse(description=u'套餐金额超限')
- if len(rule['name']) > 20:
- return JsonErrorResponse(description=u'套餐名字只能取1-20位')
- if typeCode == Const.DEVICE_TYPE_CODE_WASHER:
- name = rule['name']
- if name not in [Const.WASHER_BOX_SET_DTS, Const.WASHER_BOX_SET_KSX, Const.WASHER_BOX_SET_BZX,
- Const.WASHER_BOX_SET_DWX, Const.WASHER_BOX_SET_JRKS, Const.WASHER_BOX_SET_JRBZ,
- Const.WASHER_BOX_JRDW, Const.WASHER_BOX_SET_TQJ]:
- return JsonErrorResponse(description=u'套餐名称只能是:桶清洁、单脱水、快速洗、标准洗、大物洗、加热快速洗、加热标准洗、加热大物洗。')
- coins = rule['coins']
- useTime = rule['time']
- if name == Const.WASHER_BOX_SET_DTS:
- setConfig[Const.WASHER_BOX_DTS] = {'price': int(coins), 'time': int(useTime)}
- elif name == Const.WASHER_BOX_SET_KSX:
- setConfig[Const.WASHER_BOX_KS] = {'price': int(coins), 'time': int(useTime)}
- elif name == Const.WASHER_BOX_SET_BZX:
- setConfig[Const.WASHER_BOX_BZ] = {'price': int(coins), 'time': int(useTime)}
- elif name == Const.WASHER_BOX_SET_DWX:
- setConfig[Const.WASHER_BOX_DW] = {'price': int(coins), 'time': int(useTime)}
- elif name == Const.WASHER_BOX_SET_JRKS:
- setConfig[Const.WASHER_BOX_JRKS] = {'price': int(coins), 'time': int(useTime)}
- elif name == Const.WASHER_BOX_SET_JRBZ:
- setConfig[Const.WASHER_BOX_JRBZ] = {'price': int(coins), 'time': int(useTime)}
- elif name == Const.WASHER_BOX_SET_JRDW:
- setConfig[Const.WASHER_BOX_JRDW] = {'price': int(coins), 'time': int(useTime)}
- elif (typeCode == Const.DEVICE_TYPE_CODE_WASHER_CW) and \
- (rule['name'] not in [u'标准洗', u'快速洗', u'强力洗', u'单脱水', u'轻柔洗', u'漂洗并脱水', u'自洁', u'能效-全载', u'能效-半载',
- u'整机自检', u'电脑版自检']):
- return JsonErrorResponse(description=u'套餐名称只能是:标准洗,快速洗,强力洗,单脱水,轻柔洗,漂洗并脱水,自洁,能效-全载,能效-半载,整机自检,电脑版自检')
- elif typeCode == Const.DEVICE_TYPE_CODE_WASHER_SIMAIER:
- if rule['name'] not in [u'加强洗', u'标准洗', u'快速洗', u'单脱水']:
- return JsonErrorResponse(description=u'套餐名称只能是:加强洗,标准洗,快速洗,单脱水')
- elif typeCode == Const.DEVICE_TYPE_CODE_HUITENG:
- if rule['name'] not in [u'单脱水', u'快速洗', u'标准洗', u'大物洗']:
- return JsonErrorResponse(description=u'套餐名称只能是:单脱水,快速洗,标准洗,大物洗')
- elif typeCode == Const.DEVICE_TYPE_CODE_CAR_CHARGING_CY:
- price = rule.get("price")
- coins = rule.get("coins")
- unit = rule.get("unit")
- time = rule.get("time")
- if price != coins:
- return JsonErrorResponse(description=u'请将金币和套餐值设置相同')
- if unit != u"次":
- return JsonErrorResponse(description=u'计费单位只能是:次')
- if int(time) != 1:
- return JsonErrorResponse(description=u"计费次数只能是:1")
- elif typeCode in [Const.DEVICE_TYPE_CODE_WASHER_CY_HS,Const.DEVICE_TYPE_CODE_WASHER_CY_HS_YUCHUAN]:
- if rule['name'] not in [u'大物洗', u'标准洗', u'快速洗', u'单脱水']:
- return JsonErrorResponse(description=u'套餐名称只能是:大物洗,标准洗,快速洗,单脱水')
- if rule['unit'] != "分钟":
- return JsonErrorResponse(description=u"请将套餐的价格设置为分钟")
- if rule["name"] == u"单脱水" and (int(rule["time"]) > 9 or int(rule["time"]) < 5):
- return JsonErrorResponse(description=u"单脱水时间范围为5-9分钟")
- if rule["name"] == u"快速洗" and (int(rule["time"]) > 32 or int(rule["time"]) < 20):
- return JsonErrorResponse(description=u"快速洗时间范围为20-32分钟")
- if rule["name"] == u"标准洗" and (int(rule["time"]) > 43 or int(rule["time"]) < 35):
- return JsonErrorResponse(description=u"标准洗时间范围为35-43分钟")
- if rule["name"] == u"大物洗" and (int(rule["time"]) > 53 or int(rule["time"]) < 45):
- return JsonErrorResponse(description=u"大物洗时间范围为45-53分钟")
- if int(float(rule["coins"])) > 15 or int(float(rule["price"])) > 15:
- return JsonErrorResponse(description=u"套餐价格不得大于15")
- elif typeCode in [Const.DEVICE_TYPE_CODE_WASHER_CY_HJ]:
- if rule['name'] not in [u'大物洗', u'标准洗', u'快速洗', u'单脱水']:
- return JsonErrorResponse(description=u'套餐名称只能是:大物洗,标准洗,快速洗,单脱水')
- if rule['unit'] != "分钟":
- return JsonErrorResponse(description=u"请将套餐的价格设置为分钟")
- if rule["name"] == u"单脱水" and (int(rule["time"]) > 15 or int(rule["time"]) < 5):
- return JsonErrorResponse(description=u"单脱水时间范围为5-15分钟")
- if rule["name"] == u"快速洗" and (int(rule["time"]) > 35 or int(rule["time"]) < 20):
- return JsonErrorResponse(description=u"快速洗时间范围为20-35分钟")
- if rule["name"] == u"标准洗" and (int(rule["time"]) > 50 or int(rule["time"]) < 35):
- return JsonErrorResponse(description=u"标准洗时间范围为35-50分钟")
- if rule["name"] == u"大物洗" and (int(rule["time"]) > 65 or int(rule["time"]) < 50):
- return JsonErrorResponse(description=u"大物洗时间范围为50-65分钟")
- if int(float(rule["coins"])) > 15 or int(float(rule["price"])) > 15:
- return JsonErrorResponse(description=u"套餐价格不得大于15")
- elif typeCode in [Const.DEVICE_TYPE_CODE_WASHER_CY_HJ_1]:
- if rule['name'] not in [u'大物洗', u'标准洗', u'快速洗', u'单脱水']:
- return JsonErrorResponse(description=u'套餐名称只能是:大物洗,标准洗,快速洗,单脱水')
- if rule['unit'] != "分钟":
- return JsonErrorResponse(description=u"请将套餐的价格设置为分钟")
- if rule["name"] == u"单脱水" and (int(rule["time"]) > 15 or int(rule["time"]) < 5):
- return JsonErrorResponse(description=u"单脱水时间范围为5-15分钟")
- if rule["name"] == u"快速洗" and (int(rule["time"]) > 35 or int(rule["time"]) < 18):
- return JsonErrorResponse(description=u"快速洗时间范围为18-35分钟")
- if rule["name"] == u"标准洗" and (int(rule["time"]) > 45 or int(rule["time"]) < 30):
- return JsonErrorResponse(description=u"标准洗时间范围为30-45分钟")
- if rule["name"] == u"大物洗" and (int(rule["time"]) > 55 or int(rule["time"]) < 40):
- return JsonErrorResponse(description=u"大物洗时间范围为40-55分钟")
- if int(float(rule["coins"])) > 15 or int(float(rule["price"])) > 15:
- return JsonErrorResponse(description=u"套餐价格不得大于15")
- elif typeCode == "1003053":
- if rule['name'] not in [u'加时烘干', u'快速烘干', u'标准烘干', u'特别烘干']:
- return JsonErrorResponse(description=u'套餐名称只能是:加时烘干,快速烘干,标准烘干,特别烘干')
- if rule['unit'] != "分钟":
- return JsonErrorResponse(description=u"请将套餐的价格设置为分钟")
- if rule["name"] == u"加时烘干" and (int(rule["time"]) > 20 or int(rule["time"]) < 5):
- return JsonErrorResponse(description=u"加时烘干时间范围为5-20分钟")
- if rule["name"] == u"快速烘干" and (int(rule["time"]) > 40 or int(rule["time"]) < 20):
- return JsonErrorResponse(description=u"快速洗时间范围为20-40分钟")
- if rule["name"] == u"标准烘干" and (int(rule["time"]) > 50 or int(rule["time"]) < 30):
- return JsonErrorResponse(description=u"标准洗时间范围为30-50分钟")
- if rule["name"] == u"特别烘干" and (int(rule["time"]) > 70 or int(rule["time"]) < 50):
- return JsonErrorResponse(description=u"大物洗时间范围为50-70分钟")
- if int(float(rule["coins"])) > 15 or int(float(rule["price"])) > 15:
- return JsonErrorResponse(description=u"套餐价格不得大于15")
- if 'id' in rule:
- ruleId = rule['id']
- else:
- ruleId = list(set(range(1, 71)) - set([int(ruleId) for ruleId in washConfig.keys()]) - set(existIds))[0]
- # TODO 需要统一类型.这里为云南霍博单独做
- dealer = request.user # type: Dealer
- if ('coins_be_float' not in agent.features) and (not dealer.supports('coins_be_float')):
- if int(float(rule['coins'])) != float(rule['coins']):
- return JsonErrorResponse(description=u'金币只能是整数')
- washConfig[str(ruleId)] = {
- 'name': rule['name'],
- 'coins': int(float(rule['coins'])),
- 'price': float(rule['price']),
- 'time': float(rule.get('time', 0)),
- 'description': rule.get('description', ''),
- 'imgList': rule.get('imgList', []),
- 'unit': rule.get('unit', u'分钟'),
- 'switch': rule.get('switch', True),
- 'sn': rule.get('sn'),
- }
- else:
- washConfig[str(ruleId)] = {
- 'name': rule['name'],
- 'coins': float(rule['coins']),
- 'price': float(rule['price']),
- 'time': float(rule.get('time', 0)),
- 'description': rule.get('description', ''),
- 'imgList': rule.get('imgList', []),
- 'unit': rule.get('unit', u'分钟'),
- 'switch': rule.get('switch', True),
- 'sn': rule.get('sn'),
- }
- if rule.get('pulse'):
- washConfig[str(ruleId)].update({
- 'pulse': rule.get('pulse'),
- })
- if rule.get('basePrice'):
- washConfig[str(ruleId)].update({
- 'basePrice': rule.get('basePrice'),
- })
- if rule.get('billingMethod') and rule['billingMethod'] != CONSUMETYPE.BILL_AS_SERVICE:
- washConfig[str(ruleId)].update({
- 'billingMethod': rule['billingMethod'],
- })
- if rule.get('autoStop') != None:
- washConfig[str(ruleId)].update({
- 'basePrice': rule.get('basePrice'),
- })
- if rule.get('autoRefund') != None:
- washConfig[str(ruleId)].update({
- 'basePrice': rule.get('basePrice'),
- })
- if typeCode in [Const.DEVICE_TYPE_CODE_WASHER_CY_HS, Const.DEVICE_TYPE_CODE_WASHER_CY_HS_YUCHUAN, Const.DEVICE_TYPE_CODE_WASHER_CY_HS_HONGGAN]:
- if len(serviceList) != 4:
- return JsonErrorResponse(description=u'请勿增加或删除套餐')
- # 如果设备直接可以下发套餐信息到设备,直接到设备上修改。比如串口洗衣机、串口的充电设备等
- for devNo, dev in devDict.items():
- if dev['devType']['code'] == Const.DEVICE_TYPE_CODE_WASHER:
- smartBox = dev.deviceAdapter # type: WasherBox
- try:
- curConfig = smartBox.get_wash_config()
- except ServiceException, e:
- logger.exception('get washconfig to device=%s error=%s' % (devNo, e))
- return JsonErrorResponse(description=u'读取设备套餐信息遇到错误:%s,请稍候再试试哦' % (e.result.get('description')))
- try:
- curConfig.update(setConfig)
- smartBox.set_wash_config(curConfig)
- except ServiceException, e:
- logger.exception('set washconfig to device=%s error=%s' % (devNo, e))
- return JsonErrorResponse(description=u'保存套餐到设备遇到错误:%s,请稍候再试试哦' % (e.result.get('description')))
- if dev['devType']['code'] == Const.DEVICE_TYPE_CODE_HUITENG:
- smartBox = dev.deviceAdapter # type: washerHTBox
- cmdFlagDict = {u'单脱水': {'coins': '01', 'time': '09', 'baseTime': 5},
- u'快速洗': {'coins': '02', 'time': '08', 'baseTime': 20},
- u'标准洗': {'coins': '03', 'time': '07', 'baseTime': 35},
- u'大物洗': {'coins': '04', 'time': '06', 'baseTime': 45}}
- oldConfig = dev['washConfig']
- for ruleId, rule in oldConfig.items():
- try:
- newRule = washConfig.get(ruleId)
- if newRule['coins'] != rule['coins']:
- smartBox.set_normal_value(cmdFlagDict[newRule['name']]['coins'], newRule['coins'])
- if newRule['time'] != rule['time']:
- baseTime = cmdFlagDict[newRule['name']]['baseTime']
- if newRule['time'] < baseTime:
- return JsonErrorResponse(description=u'您设置的套餐%s时间%s分钟,不能低于基础时间%s分钟' % (
- newRule['name'], newRule['time'], baseTime))
- addTime = newRule['time'] - baseTime
- smartBox.set_normal_value(cmdFlagDict[newRule['name']]['time'], addTime)
- except ServiceException, e:
- return JsonErrorResponse(description=u'保存套餐到设备遇到错误:%s,请重试哦' % (e.result.get('description')))
- if dev['devType']['code'] in [Const.DEVICE_TYPE_CODE_WASHER_CY_HS, Const.DEVICE_TYPE_CODE_WASHER_CY_HS_YUCHUAN]:
- box = dev.deviceAdapter
- washPriceMap = {
- u"单脱水": "priceDt",
- u"快速洗": "priceKs",
- u"标准洗": "priceBz",
- u"大物洗": "priceDw"
- }
- washTimeMap = {
- u"单脱水": "timeDt",
- u"快速洗": "timeKs",
- u"标准洗": "timeBz",
- u"大物洗": "timeDw"
- }
- priceData = {}
- timeData = {}
- for _, c in washConfig.items():
- try:
- priceData[washPriceMap.get(c.get("name"))] = c.get("coins")
- timeData[washTimeMap.get(c.get("name"))] = c.get("time")
- except Exception as e:
- break
- else:
- try:
- box.set_config_82(priceData)
- box.set_config_83(timeData)
- except ServiceException, e:
- return JsonErrorResponse(description=u'保存套餐遇到错误,请稍候再试')
- # 烘干机
- if dev['devType']['code'] == Const.DEVICE_TYPE_CODE_WASHER_CY_HS_HONGGAN:
- box = dev.deviceAdapter
- hongganPriceMap = {
- u"加时烘干": "priceDt",
- u"快速烘干": "priceKs",
- u"标准烘干": "priceBz",
- u"特别烘干": "priceDw"
- }
- hongganTimeMap = {
- u"加时烘干": "timeDt",
- u"快速烘干": "timeKs",
- u"标准烘干": "timeBz",
- u"特别烘干": "timeDw"
- }
- priceData = {}
- timeData = {}
- for _, c in washConfig.items():
- try:
- priceData[hongganPriceMap.get(c.get("name"))] = c.get("coins")
- timeData[hongganTimeMap.get(c.get("name"))] = c.get("time")
- except Exception as e:
- break
- else:
- try:
- box.set_config_82(priceData)
- box.set_config_83(timeData)
- except ServiceException, e:
- return JsonErrorResponse(description=u'保存套餐遇到错误,请稍候再试')
- try:
- dev['washConfig'] = washConfig
- otherConf = dev.get('otherConf', {})
- otherConf['displaySwitchs'] = displaySwitchs
- Device.get_collection().update({'devNo': dev['devNo']}, {'$set': {'washConfig': dev['washConfig'], 'otherConf':otherConf}})
- request.user.defaultWashConfig[dev['devType']['id']] = dev['washConfig'].values()
- request.user.save()
- Device.invalid_device_cache(devNo)
- except ServiceException, e:
- logger.exception('update device washconfig error=%s,devNo=%s,washConfig=%s'
- % (e, devNo, dev['washConfig']))
- return JsonErrorResponse(description=u'保存套餐遇到错误,请稍候再试')
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'设置默认组失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def setDefaultGroup(request):
- ownerId = str(request.user.bossId)
- groupId = request.POST.get('groupId', None)
- if groupId is None:
- return JsonErrorResponse(description=u"缺少参数")
- try:
- success, description, group = Group.update_group(group_id=groupId, isDefault=True)
- return JsonOkResponse() if success else JsonErrorResponse(description=description)
- except Exception, e:
- logger.exception('update error=%s' % e)
- return JsonResponse({'result': 0, 'description': u"系统繁忙,请稍后再试", 'payload': {}})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def logout(request):
- agentId = request.user.agentId
- auth.logout(request)
- response = JsonResponse({'result': 1, 'payload': agentId})
- # 删除不在使用的COOKIE
- response.delete_cookie(key='hasagent')
- return response
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def wxconfig(request):
- url = request.GET.get('href')
- if not url:
- return JsonResponse({'result': 0, 'description': u'参数错误', 'payload': {}})
- value = get_wx_config(request.user, url)
- logger.exception('wx config url = %s' % url)
- return JsonResponse({'result': 1, 'description': None, 'payload': {'wxconfig': value}})
- @require_GET
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取库存详情失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def stockDetails(request):
- logicalCode = request.GET.get('logicalCode')
- devNo = Device.get_devNo_by_logicalCode(logicalCode)
- dev = Device.get_dev(devNo)
- if not dev:
- return JsonErrorResponse(description=u'找不到设备')
- return JsonResponse({'result': 1, "description": None, "payload": {"quantity": dev['quantity']}})
- @require_POST
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'更新库存失败,请重试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def updateStockQuantity(request):
- payload = json.loads(request.body)
- lc = payload.get('logicalCode')
- quantity = int(payload.get('quantity', 0))
- devNo = Device.get_devNo_by_logicalCode(lc)
- dev = Device.get_dev(devNo)
- if dev['quantity'] > quantity:
- stockType = 'remove'
- stockNum = dev['quantity'] - quantity
- else:
- stockType = 'add'
- stockNum = quantity - dev['quantity']
- result = Device.update_field(dev_no=devNo, update=True, quantity=quantity, consumptionQuantity=0)
- if not result:
- return JsonResponse({'result': 0, 'description': u'更新库存失败,请重试'})
- stockTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- StockRecord.get_collection().insert(
- {'logicCode': lc, 'imei': dev['devNo'], 'stockType': stockType, 'stockTime': stockTime, 'number': stockNum})
- return JsonResponse({'result': 1, 'description': None, 'payload': {}})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getStockRecord(request):
- lc = request.GET.get('logicalCode')
- if not lc:
- return JsonResponse({'result': 0, 'description': u'未接收到设备编码,请刷新重试', 'payload': {}})
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- startTime = defaultTodayDate(request.GET.get('startTime', None)) + ' ' + '00:00:00'
- endTime = defaultTodayDate(request.GET.get('endTime', None)) + ' ' + '23:59:59'
- rcds = StockRecord.get_collection().find({'logicCode': lc, 'stockTime': {'$gte': startTime, '$lte': endTime}}).sort(
- 'stockTime', -1)
- add, cost = 0, 0
- sIndex = (pageIndex - 1) * pageSize
- eIndex = pageIndex * pageSize
- ii = 0
- dataList = []
- for rcd in rcds:
- name = ''
- if rcd['stockType'] == 'add':
- add += rcd['number']
- name = u'增加库存 ' + rcd.get('more', '')
- elif rcd['stockType'] == 'remove':
- cost += rcd['number']
- name = u'减少库存 ' + rcd.get('more', '')
- elif rcd['stockType'] == 'consume':
- cost += rcd['number']
- name = u'用户购买 ' + rcd.get('more', '')
- elif rcd['stockType'] == 'adFree':
- cost += rcd['number']
- name = u'吸粉发放 ' + rcd.get('more', '')
- if sIndex <= ii < eIndex:
- dataList.append({'name': name, 'time': rcd['stockTime'], 'number': rcd['number']})
- ii += 1
- devNo = Device.get_devNo_by_logicalCode(lc)
- dev = Device.get_dev(devNo)
- para = {'total': ii, 'add': add, 'cost': cost, 'quantity': dev['quantity'], 'dataList': dataList}
- return JsonResponse({'result': 1, 'description': None, 'payload': para})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def toggleSwitches(request):
- paraDict = json.loads(request.body) if request.body else {}
- if not paraDict:
- return JsonErrorResponse(description=u'接收数据为空,请重试')
- ownerId = request.user.bossId # type: ObjectId
- if paraDict.get("hasTempPackage", None) == True:
- paraDict["displayTempPackage"] = True
- success = Dealer.update_dealer(ownerId, **paraDict)
- if not success:
- return JsonErrorResponse(description=u'更新失败,请重试')
- else:
- return JsonOkResponse()
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def clearDeviceStatistics(request):
- lc = request.POST.get('logicalCode')
- devNo = Device.get_devNo_by_logicalCode(lc)
- dev = Device.get_dev(devNo)
- if not dev:
- return JsonErrorResponse(description=u'找不到设备')
- if dev['ownerId'] != str(request.user.bossId):
- return JsonResponse({'result': 0, 'description': u'非法操作', 'payload': {}})
- if dev.get('devType', {}).get('code', '') not in [Const.DEVICE_TYPE_CODE_WASHCAR_LSHB]:
- return JsonResponse({'result': 0, 'description': u'您的设备类型不支持此操作哦', 'payload': {}})
- try:
- smartBox = ActionDeviceBuilder.create_action_device(dev)
- smartBox.clear_dev_feecount()
- except ServiceException, e:
- return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}})
- return JsonResponse({'result': 1, 'description': u'', 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getDeviceFunction(request):
- payload = json.loads(request.body)
- lc = payload.get("logicalCode")
- if isinstance(lc, list) and len(lc):
- lc = lc[0]
- else:
- raise JsonErrorResponse(description=u"无效的设备编号")
- devNo = Device.get_devNo_by_logicalCode(lc)
- dev = Device.get_dev(devNo)
- if not dev:
- return JsonResponse({'result': 0, 'description': u'未找到该设备', 'payload': {}})
- try:
- smartBox = ActionDeviceBuilder.create_action_device(dev)
- setConf = smartBox.get_dev_setting()
- if setConf is None:
- return JsonResponse({'result': 0, 'description': u'您的设备类型不支持此操作哦', 'payload': {}})
- if len(payload.get("logicalCode")) > 1:
- serviceCache.set('lastsettingConf_owner%s' % (str(request.user.id)), setConf, 600)
- else:
- caches['devmgr'].set('settingConf_%s' % (devNo,), setConf, 600)
- return JsonResponse({'result': 1, 'description': u'', 'payload': setConf})
- except ServiceException, e:
- return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getDeviceFunctionForIC(request):
- payload = json.loads(request.body)
- lc = payload.get("logicalCode")
- if isinstance(lc, list) and len(lc):
- lc = lc[0]
- else:
- raise JsonErrorResponse(description=u"无效的设备编号")
- devNo = Device.get_devNo_by_logicalCode(lc)
- dev = Device.get_dev(devNo)
- if not dev:
- return JsonResponse({'result': 0, 'description': u'未找到该设备', 'payload': {}})
- try:
- smartBox = ActionDeviceBuilder.create_action_device(dev)
- setConf = smartBox.get_IC_card_password()
- if setConf is None:
- return JsonResponse({'result': 0, 'description': u'您的设备类型不支持此操作哦', 'payload': {}})
- caches['devmgr'].set('settingConf_%s' % (devNo,), setConf, 600)
- return JsonResponse({'result': 1, 'description': u'', 'payload': setConf})
- except ServiceException, e:
- return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def setDeviceFunction(request):
- # type: (WSGIRequest)->JsonResponse
- payload = json.loads(request.body)
- lc = payload.get("logicalCode")
- if isinstance(lc, list) and len(lc):
- lc = lc[0]
- else:
- raise JsonErrorResponse(description=u"无效的设备编号")
- requestBody = RequestBodyDict({"POST": payload})
- devNo = Device.get_devNo_by_logicalCode(lc)
- dev = Device.get_dev(devNo)
- if not dev:
- return JsonErrorResponse(description=u'找不到设备')
- if dev['ownerId'] != str(request.user.bossId):
- return JsonResponse({'result': 0, 'description': u'非法操作', 'payload': {}})
- lastSetConf = caches['devmgr'].get('settingConf_%s' % (devNo,))
- box = ActionDeviceBuilder.create_action_device(dev)
- try:
- box.set_device_function(requestBody, lastSetConf)
- except ServiceException, e:
- logger.exception('set info to device=%s error=%s' % (devNo, e))
- return JsonResponse(
- {'result': 0, 'description': u'设置参数遇到错误:%s' % (e.result.get('description', '')), 'payload': {}})
- if lastSetConf is not None:
- caches['devmgr'].set('settingConf_%s' % devNo, lastSetConf)
- return JsonResponse({'result': 1, 'description': None, 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def setDeviceFunctionParam(request):
- # type: (WSGIRequest)->JsonResponse
- updateConf = json.loads(request.body)
- logicalCodes = updateConf.pop('logicalCode')
- # 替代品 先将 request 和 adapter的功能函数解耦 后续逐步修改
- requestBody = RequestBodyDict({"POST": updateConf})
- if len(logicalCodes) > 1:
- setMode = updateConf.pop('modifyMode', None)
- dev = Device.get_dev_by_l(logicalCodes[0])
- dev_owner = dev.ownerId
- dev_type_code = dev.devType.get('code')
- for logicalCode in logicalCodes[1:]:
- dev = Device.get_dev_by_l(logicalCode)
- if dev_owner != dev.ownerId or dev_type_code != dev.devType.get('code'):
- return JsonErrorResponse(description=u"设备经销商不同或者不同类型设备")
- beforeConf = serviceCache.get('lastsettingConf_owner%s' % (str(request.user.id))) # type: Dict
- if not beforeConf:
- return JsonErrorResponse(description=u"查询当前配置信息失败")
- if setMode == 'diff':
- # 找出发生改变的参数项
- for key, oldValue in beforeConf.iteritems():
- if key in updateConf and str(updateConf[key]) == str(oldValue):
- updateConf.pop(key)
- if not updateConf:
- return JsonErrorResponse(description=u"您没有修改任何参数")
- payload = {'updateConf': updateConf, 'lastSetConf': None, 'logicalCodes': logicalCodes}
- else:
- payload = {'updateConf': updateConf, 'lastSetConf': beforeConf, 'logicalCodes': logicalCodes}
- payload.update({
- 'operationId': '{}_{}'.format(str(request.user.id), int(time.time()))
- })
- from taskmanager.mediator import task_caller
- task_caller('batch_set_device_params', **payload)
- serviceCache.set(payload['operationId'], payload, 600)
- return JsonResponse({'result': 1, 'description': None, 'payload': {'operationId': payload['operationId']}})
- else:
- logicalCode = logicalCodes[0]
- dealer = Dealer.objects(id=str(request.user.id)).first()
- if dealer is None:
- return JsonErrorResponse(description=u"设备的经销商不存在")
- devNo = Device.get_devNo_by_logicalCode(logicalCode)
- dev = Device.get_dev(devNo)
- if dev is None:
- return JsonResponse({'result': 0, 'description': u'没有找到设备', 'payload': {}})
- if dev['ownerId'] != str(request.user.bossId):
- return JsonResponse({'result': 0, 'description': u'非法操作', 'payload': {}})
- beforeConf = caches['devmgr'].get('settingConf_%s' % (devNo,))
- if not beforeConf:
- try:
- beforeConf = dev.deviceAdapter.get_dev_setting()
- if not beforeConf:
- return JsonResponse({'result': 0, 'description': u'当前设备不支持该操作', 'payload': {}})
- except Exception as e:
- logger.exception(e)
- return JsonResponse({'result': 0, 'description': u'查询设备当前配置信息失败', 'payload': {}})
- operation = OperatorLog.record_dev_setting_changes_log(
- dealer, 'record_someone_set_devSettings', dev['logicalCode'], dev['devType']['code'],
- {
- 'beforeCacheStr': json.dumps(beforeConf), 'afterCacheStr': json.dumps(updateConf)
- }) # type: OperatorLog
- try:
- dev.deviceAdapter.set_device_function_param(requestBody, beforeConf)
- operation.update(content__status='success')
- return JsonResponse({'result': 1, 'description': None, 'payload': {}})
- except ServiceException, e:
- logger.info('error happened, error=%s' % (e,))
- operation.update(content__status='fail', content_desc=e.result.get('description'))
- return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}})
- except InvalidParameter as e:
- logger.exception(e)
- operation.update(content__status='fail', content_desc=e.message)
- return JsonResponse({'result': 0, 'description': e.message, 'payload': {}})
- except Exception, e:
- operation.update(content__status='fail', content_desc=u'系统异常')
- logger.exception('error happened, error=%s' % (e,))
- return JsonResponse({'result': 0, 'description': u'系统异常,请检查输入参数,或者稍后重试', 'payload': {}})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def deviceParamsResult(request):
- user = request.user
- operationId = request.GET.get('operationId', None)
- if not operationId:
- return JsonResponse({'result': 1, 'description': None, 'payload': {}})
- payload = serviceCache.get(operationId, {})
- if not payload:
- operations = OperatorLog.objects.filter(operatorId=str(user.id),
- role=user.role,
- content__operationId=operationId)
- dataList = list(map(lambda operation: {'id': str(operation.id), 'logicalCode': operation.content['logicalCode'],
- 'status': operation.content.get('status')}, operations))
- else:
- logicalCodes = payload.get('logicalCodes', [])
- operations = OperatorLog.objects.filter(operatorId=str(user.id),
- role=user.role,
- content__logicalCode__in=logicalCodes,
- content__operationId=operationId)
- dataList = list(map(lambda operation: {'id': str(operation.id), 'logicalCode': operation.content['logicalCode'],
- 'status': operation.content.get('status')}, operations))
- if len(operations) != len(logicalCodes):
- leftLogicalCodes = set(logicalCodes) - set(operations.values_list('logicalCode'))
- for logicalCode in leftLogicalCodes:
- dataList.append({'id': None, 'logicalCode': logicalCode, 'status': 'waiting'})
- return JsonResponse({'result': 1, 'description': None, 'payload': {'dataList':dataList}})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def retryingSettingsDeviceParams(request):
- dev_oper_id = request.GET.get('id')
- operation = OperatorLog.objects.filter(id=dev_oper_id).first() # type: OperatorLog
- logicalCode = operation.content['logicalCode']
- dev = Device.get_dev_by_l(logicalCode) # type: DeviceDict
- if not dev:
- return JsonResponse({'result': 0, 'description': u'该设备不存在', 'payload': {}})
- if dev.ownerId != request.user.bossId:
- return JsonResponse({'result': 0, 'description': u'您无权操作该设备', 'payload': {}})
- try:
- if operation.operatorName == 'record_someone_set_devSettings':
- updateConf = json.loads(operation.content.get('updateConfStr'))
- beforeCacheStr = json.loads(operation.content.get('beforeCacheStr'))
- requestBody = RequestBodyDict({"POST": updateConf})
- dev.deviceAdapter.set_device_function(requestBody, beforeCacheStr)
- dev.deviceAdapter.set_device_function_param(requestBody, beforeCacheStr)
- elif operation.operatorName == 'setServerSetting':
- payload = json.loads(operation.content.get('after'))
- dev.deviceAdapter.set_server_setting(payload)
- except ServiceException, e:
- logger.info('error happened, error=%s' % (e,))
- return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}})
- except InvalidParameter as e:
- logger.exception(e)
- return JsonResponse({'result': 0, 'description': e.message, 'payload': {}})
- else:
- operation.update(content__status='success')
- return JsonResponse({'result': 1, 'description': '重试成功', 'payload': {'status': 'success'}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取卡列表失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getUserCardList(request):
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- searchKey = str(request.GET.get('searchKey', ''))
- userId = str(request.GET.get('userId', ''))
- equipmentGroupId = str(request.GET.get('equipmentGroupId'))
- frozen = request.GET.get("frozen", None)
- dealerId = str(request.user.bossId)
- queryDict = {
- "dealerId": dealerId,
- 'openId': userId or {'$exists': True}
- }
- if frozen:
- queryDict.update({"frozen": bool(int(frozen))})
- if searchKey:
- queryDict.update(search_query(['cardName', 'phone', "cardNo"], searchKey).to_query(Card))
- if equipmentGroupId:
- queryDict.update({'groupId': equipmentGroupId})
- cards = Card.objects.filter(__raw__=queryDict).skip((pageIndex - 1) * pageSize).limit(pageSize)
- dataList = list()
- for card in cards: # type: Card
- dataList.append({
- "cardName": card.cardName,
- "phone": card.phone,
- "groupId": card.groupId,
- "groupName": card.group.groupName if card.group else "",
- "cardId": str(card.id),
- "bindStatus": card.isBinded,
- "dealerId": card.dealerId,
- "remarks": card.remarks,
- "balance": card.balance,
- "cardNo": card.cardNo,
- "frozen": int(card.frozen)
- })
- payload = {
- "total": get_paginate(dataList, pageSize=pageSize, pageIndex=pageIndex),
- "dataList": dataList,
- "agentId": request.user.agentId
- }
- return JsonResponse({"result": 1, "description": "", "payload": payload})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取详情失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getUserCard(request):
- cardId = request.GET.get("cardId", "")
- try:
- card = Card.objects.get(id=cardId)
- except DoesNotExist:
- return JsonErrorResponse(description=u"无效的卡")
- except Exception as e:
- logger.exception(e)
- return JsonErrorResponse(description=u"获取卡详情失败,请刷新页面试试")
- if card.dealerId != str(request.user.bossId):
- return JsonErrorResponse(u"获取详情失败")
- group = card.group
- data = {
- "cardId": cardId,
- "cardNo": card.cardNo,
- "cardName": card.cardName,
- "groupId": card.groupId,
- "dealerId": card.dealerId,
- "groupName": group.groupName if group is not None else '',
- "frozen": card.frozen,
- "phone": card.phone,
- "status": card.status,
- "bindStatus": card.isBinded,
- "balance": "{:.2f}".format(float(card.balance)),
- "chargeBalance": "{:.2f}".format(float(card.chargeBalance)),
- "bestowBalance": "{:.2f}".format(float(card.bestowBalance)),
- "cardType": card.cardType
- }
- return JsonOkResponse(payload=data)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"编辑卡失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def editCard(request):
- """
- 经销商端 编辑卡片信息 可编辑内容 为 绑定设备组 卡名称 联系方式
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- cardId = payload.get("cardId")
- cardName = payload.get("cardName")
- phone = payload.get("phone")
- groupId = payload.get("groupId")
- try:
- card = Card.objects.get(id=cardId)
- except DoesNotExist:
- return JsonErrorResponse(description=u"修改卡失败")
- if phone and not PHONE_NUMBER_RE.match(phone):
- return JsonErrorResponse(description=u"手机号码输入错误")
- if cardName and not NAME_RE.match(cardName):
- return JsonErrorResponse(description=u"请输入正确格式的名称(2-20位)")
- if card.dealerId != str(request.user.bossId):
- return JsonErrorResponse(description=u"不是您的卡片,无权修改")
- group = Group.get_group(groupId)
- if not group:
- return JsonErrorResponse(description=u"请选择正确的设备组")
- if group.get("ownerId") != str(request.user.bossId):
- return JsonErrorResponse(description=u"请选择正确的设备组")
- card.cardName = cardName
- card.phone = phone
- card.groupId = groupId
- card.save()
- return JsonOkResponse()
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"录卡失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def saveEntityCard(request):
- # type: (WSGIRequest)->JsonResponse
- payload = json.loads(request.body)
- cardNo = payload.get('cardNo', '')
- phone = payload.get('phone', '')
- cardName = payload.get('cardName', '')
- groupId = payload.get("groupId", "")
- dealerId = str(request.user.bossId)
- # 卡号前置去0
- if cardNo.isdigit():
- cardNo = str(int(cardNo))
- if not cardNo or not Card.check_card_no(cardNo):
- return JsonErrorResponse(description=u"卡号不符合规则,请输入正确的卡号")
- groupIds = Group.get_group_ids_of_dealer(dealerId)
- if not groupId or groupId not in groupIds:
- return JsonErrorResponse(description=u"请选择正确的设备组")
- if phone and not PHONE_NUMBER_RE.match(phone):
- return JsonErrorResponse(description=u"手机号码输入错误")
- if cardName and not NAME_RE.match(cardName):
- return JsonResponse({"result": 0, "description": u"请输入正确格式的名称(2-20位)"})
- agentId = request.user.agentId
- # 基于卡号找 代理商下的卡 或者平台下的卡
- card = Card.objects.filter(Q(agentId=agentId) | Q(agentId=''), cardNo=cardNo).first()
- if not card:
- card = Card(
- cardNo=cardNo,
- dealerId=dealerId,
- agentId=agentId,
- cardName=cardName,
- groupId=groupId,
- phone=phone,
- openId=Const.DEFAULT_CARD_OPENID
- ).save()
- return JsonResponse({"result": 1, "description": u"录入成功", "payload": {'cardId':str(card.id)}})
- else:
- if card.dealerId: # 有经销商注册
- if card.dealerId == dealerId:
- return JsonErrorResponse(description=u"{} 卡已经被您收录,请不要重复收录".format(cardNo))
- else:
- return JsonErrorResponse(description="{} 卡已被其他经销商录入,请确认卡号不要重复".format(cardNo))
- else: # 此代理商平台下没有经销商注册该卡片
- card.dealerId = dealerId
- card.agentId = agentId
- card.cardName = cardName
- card.groupId = groupId
- card.phone = phone
- card.openId = Const.DEFAULT_CARD_OPENID
- card.save()
- return JsonResponse({"result": 1, "description": u"录入成功", "payload": {'cardId': str(card.id)}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"补卡失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def swapCardNo(request):
- """
- 补卡 需要生成补卡记录,不重新创建新卡 如果新卡的卡号已经存在但是没有绑定用户并且内部没余额
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- cardNo = payload.get("cardNo", "")
- cardId = payload.get("cardId")
- dealerId = str(request.user.bossId)
- # 卡号前置去0
- if cardNo.isdigit():
- cardNo = str(int(cardNo))
- if not Card.check_card_no(cardNo):
- return JsonErrorResponse(description=u"无效的卡号,卡号长度不能超过10位")
- try:
- oldCard = Card.objects.get(id=cardId)
- except DoesNotExist:
- return JsonErrorResponse(description=u"查询旧卡失败")
- if oldCard.cardNo == cardNo:
- return JsonErrorResponse(description=u"卡号一致无需修改")
- if oldCard.dealerId != dealerId:
- return JsonErrorResponse(description=u"无权编辑此卡")
- checkStatus, checkMsg = Card.check_swap_card_no(cardNo, dealerId, oldCard.agentId)
- if not checkStatus:
- return JsonErrorResponse(description=checkMsg)
- # 直接将卡号更新掉,然后新建一条换卡记录
- oldCard.update(cardNo=cardNo)
- SwapCardRecord.add_record(oldCard.cardNo, cardNo, oldCard.agentId, str(request.user.id))
- return JsonOkResponse()
- @record_operation_behavior()
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def deleteInitCard(request):
- cardId = json.loads(request.body).get("cardId")
- card = Card.objects.filter(id=cardId, dealerId=str(request.user.bossId)).first()
- if not card:
- return JsonResponse({"result": 0, "description": u"未找到该实体卡", "payload": {}})
- updated = card.clear_card()
- if not updated:
- return JsonErrorResponse(description=u'操作失败')
- return JsonResponse({"result": 1, "description": u"删除成功", "payload": {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取卡记录失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getUserCardRecord(request):
- # type: (WSGIRequest)->JsonResponse
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- startTime = request.GET.get('startTime', 10)
- endTime = request.GET.get('endTime', 10)
- cardId = request.GET.get('cardId', None)
- type = request.GET.get('type', None)
- card = Card.objects.get(id=cardId)
- if type == "chargeCard":
- dataList = []
- # TODO zjl 订单统一 不要这样搞得很别扭
- viaMap = {
- u"退币": "refund",
- u"充值": "chargeCard"
- }
- for item in CardRechargeRecord.get_collection().find({
- 'cardId': cardId,
- 'dateTimeAdded': {'$gte': to_datetime(startTime + " 00:00:00"),
- '$lte': to_datetime(endTime + " 23:59:59")}}).sort("dateTimeAdded", -1):
- data = {
- "cardId": str(item['_id']),
- "cardNo": card.cardNo,
- "via": viaMap.get(item.get("remarks"), "chargeCard"),
- "amount": item['money'],
- "coins": item.get('coins', item['money']),
- "address": item['address'],
- "groupName": item['groupName'],
- "createdTime": item['dateTimeAdded'].strftime('%Y-%m-%d %H:%M:%S'),
- "rechargeType": item.get("rechargeType")
- }
- if item.has_key('preBalance'):
- data.update({'preBalance': item['preBalance']})
- if item.has_key('balance'):
- data.update({'balance': item['balance']})
- if item.get("remarks", None):
- data.update({'remarks': item['remarks']})
- if item.get("logicalCode"):
- data.update({"devType": Device.get_dev_by_logicalCode(item['logicalCode']).get("devType", dict()).get("name", "")})
- data.update({"logicalCode": item['logicalCode']})
- dataList.append(data)
- elif type == "consume":
- dataList = []
- rcds = CardConsumeRecord.get_collection().find(
- {'cardId': cardId, 'dateTimeAdded': {'$gte': to_datetime(startTime + " 00:00:00"),
- '$lte': to_datetime(endTime + " 23:59:59")}}).sort(
- "dateTimeAdded", -1)
- for item in rcds:
- newData = {
- "cardId": str(item['_id']),
- "cardNo": card.cardNo,
- "via": "consume",
- "devType": item['devType'],
- "amount": item['money'],
- "logicalCode": item['logicalCode'],
- "address": item['address'],
- "groupName": item['groupName'],
- "createdTime": item['dateTimeAdded'].strftime('%Y-%m-%d %H:%M:%S')
- }
- if item.has_key('balance'):
- newData.update({'balance': item['balance']})
- newData.update(item.get('servicedInfo', {}))
- dataList.append(newData)
- elif type == 'order':
- dataList = []
- for item in CardRechargeOrder.get_collection().find({
- 'cardId': cardId,
- 'dateTimeAdded': {'$gte': to_datetime(startTime + " 00:00:00"),
- '$lte': to_datetime(endTime + " 23:59:59")}}).sort("dateTimeAdded", -1):
- data = {
- "via": "order",
- "amount": item['money'],
- "coins": item.get('coins', item['money']),
- "createdTime": item['dateTimeAdded'].strftime('%Y-%m-%d %H:%M:%S'),
- "status": u'等待用户刷卡充值' if item['status'] == 'finishedPay' else u'充值完成',
- "desc": item['remarks'],
- "rechargeType": item.get("rechargeType")
- }
- if item.has_key('preBalance'):
- data.update({'preBalance': item['preBalance']})
- if item.has_key('balance'):
- data.update({'balance': item['balance']})
- dataList.append(data)
- elif type == 'cardConsume':
- card = Card.objects.filter(id=cardId).first()
- dataList = []
- orders = ConsumeRecord.get_collection().find({
- 'openId': str(card.openId),
- 'dateTimeAdded': {'$gte': to_datetime(startTime + " 00:00:00"),
- '$lte': to_datetime(endTime + " 23:59:59")}}).sort("dateTimeAdded", -1)
- for item in orders:
- data = {
- "via": "consume",
- "amount":item.get('coin', item['money']),
- "createdTime": item['dateTimeAdded'].strftime('%Y-%m-%d %H:%M:%S'),
- "orderNo":item.get('orderNo'),
- "status": u'完成',
- "desc": item['remarks']
- }
- dataList.append(data)
- else:
- return JsonResponse({"result": 0, "description": u"查询类型错误", "payload": {}})
- return JsonResponse(
- {
- "result": 1,
- "description": "",
- "payload": {
- "total": len(dataList),
- "dataList": dataList[(pageIndex - 1) * pageSize: pageIndex * pageSize]
- }
- })
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getDeviceFunctionByKey(request):
- # type: (WSGIRequest)->JsonResponse
- try:
- payload = json.loads(request.body)
- key = payload.get('key', None)
- # 兼容真谷多
- port = payload.get("portIndex", None)
- if port is not None:
- key = port
- logicalCode = payload.get('logicalCode', None)
- if isinstance(logicalCode, list) and len(logicalCode):
- logicalCode = logicalCode[0]
- devNo = Device.get_devNo_by_logicalCode(logicalCode)
- dev = Device.get_dev(devNo)
- lastSetConf = caches['devmgr'].get('settingConf_%s' % (devNo,))
- if not lastSetConf:
- lastSetConf = {}
- box = ActionDeviceBuilder.create_action_device(dev)
- payload = box.get_device_function_by_key(key)
- if payload is not None:
- if lastSetConf is None:
- lastSetConf = payload
- else:
- lastSetConf.update(payload)
- caches['devmgr'].set('settingConf_%s' % (devNo,), lastSetConf, 600)
- return JsonResponse({"result": 1, "description": "", "payload": payload})
- except ServiceException, e:
- return JsonResponse({"result": 0, "description": e.result.get('description', ''), "payload": {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'设置错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def setDeviceFunctionByKey(request):
- # type: (WSGIRequest)->JsonResponse
- payload = json.loads(request.body)
- logicalCode = payload.get('logicalCode', None)
- if isinstance(logicalCode, list) and len(logicalCode):
- logicalCode = logicalCode[0]
- else:
- return JsonErrorResponse(description=u"错误的二维码编号")
- devNo = Device.get_devNo_by_logicalCode(logicalCode)
- dev = Device.get_dev(devNo)
- keyName = payload.get('key', None)
- if keyName is None:
- return JsonResponse({"result": 0, "description": u'没有按下任何控制键', "payload": {}})
- try:
- box = ActionDeviceBuilder.create_action_device(dev)
- box.press_down_key(keyName)
- return JsonResponse({"result": 1, "description": '', "payload": {}})
- except ServiceException, e:
- logger.exception('cannot setDeviceFunctionByKey, error=%s' % (e.result.get('description', '').encode('utf-8'),))
- return JsonResponse({"result": 0, "description": e.result.get('description', ''), "payload": {}})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def wechatEntry(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 必须每次都进行鉴权
- :param request:
- :return:
- """
- current_user = request.user # type: Dealer
- if not check_role(current_user, ROLE.dealer):
- return ErrorResponseRedirect(error = u'权限错误')
- entryType = request.GET.get('type')
- if entryType not in ['simCard', 'apiQuota', 'disableAdQuota']:
- return ErrorResponseRedirect(error = u'参数错误(10001)')
- if entryType == 'simCard': # 流量卡充值
- my_agent = Agent.get_inhouse_prime_agent()
- app = get_app(my_agent, APP_TYPE.WECHAT_ENV_PAY, role = ROLE.dealer)
- elif entryType == 'apiQuota': # api设备配额数量充值
- my_agent = Agent.get_inhouse_prime_agent()
- app = get_app(my_agent, APP_TYPE.WECHAT_ENV_PAY, role=ROLE.dealer)
- elif entryType == 'disableAdQuota': # api设备配额数量充值
- my_agent = Agent.get_inhouse_prime_agent()
- app = get_app(my_agent, APP_TYPE.WECHAT_ENV_PAY, role=ROLE.dealer)
- else:
- return ErrorResponseRedirect(error=u'参数错误(10002)')
- if isinstance(app, WechatPayApp):
- auth_bridge = WechatAuthBridge(app) # type: WechatAuthBridge
- else:
- return ErrorResponseRedirect(error=u'参数错误(10003)')
- auth_code = request.GET.get(auth_bridge.auth_code_key, None)
- if auth_code:
- openId = auth_bridge.authorize(auth_code)
- if openId is not None:
- redirect = base64.b64decode(request.GET.get('payload'))
- redirect = add_query(redirect, {
- 'openId': openId
- })
- return FrontEndResponseRedirect(redirect)
- else:
- return ErrorResponseRedirect(error=u'系统繁忙,请重试')
- else:
- redirect_url = concat_server_end_url(uri='/dealer/wechat/entry?type={}'.format(entryType))
- return ExternalResponseRedirect(
- auth_bridge.generate_auth_url_base_scope(
- redirect_uri=redirect_url,
- payload=base64.b64encode(request.GET.get('redirect'))))
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'冻结卡失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def freezeCard(request):
- # type: (WSGIRequest)->JsonResponse
- payload = json.loads(request.body)
- frozen = payload.get('frozen')
- cardId = payload.get('id', '')
- try:
- card = Card.objects.get(id=cardId)
- card.frozen = frozen
- card.status = 'active'
- card.save()
- except Exception, e:
- logger.exception(e.message)
- return JsonResponse({"result": 0, "description": u'系统错误', "payload": {}})
- return JsonResponse({"result": 1, "description": '', "payload": {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getWalletWithdrawInfo(request):
- dealer = request.user # type: Dealer
- if not is_dealer(dealer):
- return ErrorResponseRedirect(error = u'子账号无提现权限')
- source_key = request.GET.get('sourceId')
- income_type = request.GET.get('sourceType')
- phone = str(dealer.monitorPhone) if dealer.monitorPhone else str(dealer.username)
- result = {
- "result": 1,
- "description": None,
- 'payload': {
- 'payOpenId': 'placeholder',
- 'phone': phone,
- 'balance': dealer.sub_balance(income_type, source_key),
- 'withdrawFeeRatio': dealer.withdrawFeeRatio,
- 'support': dealer.withdraw_support(source_key)
- }
- }
- return JsonResponse(result)
- @require_POST
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请刷新'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getFeatureList(request):
- # type: (WSGIRequest)->JsonResponse
- """
- :param request:
- :return:
- """
- currentUser = request.user # type: Dealer
- payload = json.loads(request.body)
- queryList = payload.get('list', [])
- resultFeatures = currentUser.query_feature_by_list(queryList)
- if 'blackListManage' in currentUser.features:
- resultFeatures.update({'blackListManage': True})
- return JsonOkResponse(payload=resultFeatures)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请刷新'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getOnsaleTypeList(request):
- # type: (WSGIRequest)->JsonResponse
- dataList = []
- for typeName, info in OnSale.onsaleTypeDict.items():
- dataList.append(
- {
- 'typeName': typeName,
- 'desc': info['desc'],
- 'img': info['img']
- }
- )
- return JsonResponse({'result': 1, 'description': '', 'payload': {'total': len(dataList), 'dataList': dataList}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请刷新'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getOnsaleList(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 列出所有 经销商的活动尚未删除的
- :param request:
- :return:
- """
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- searchKey = request.GET.get('searchKey', None)
- dealerId = str(request.user.bossId)
- onsales = OnSale.objects.filter(dealerId=dealerId, name__startswith=searchKey).order_by("-id")
- dataList = [_obj.to_dict() for _obj in onsales[(pageIndex - 1) * pageSize: pageIndex * pageSize]]
- return JsonOkResponse(payload={"total": len(dataList), "dataList": dataList})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请刷新'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def createOnsale(request):
- # type: (WSGIRequest)->JsonResponse
- dealerId = str(request.user.bossId)
- payload = json.loads(request.body) if request.body else {}
- if not payload:
- return JsonErrorResponse(description=u'传入数据为空')
- payload['startTime'] = to_datetime(payload['startTime'] + ' 00:00:00')
- payload['endTime'] = to_datetime(payload['endTime'] + ' 23:59:59')
- onsale = OnSale(**payload)
- name = onsale.name
- # 检查活动的名称
- count = OnSale.objects.filter(dealerId=dealerId, name=name).count()
- if count > 0:
- return JsonResponse({'result': 0, 'description': u'活动名称重复,优惠活动的名称必须唯一', 'payload': {}})
- # 检查下该经销商是否符合资格配置该活动
- if onsale.onsaleType == u"京东新人1分购":
- dealer = Dealer.objects.get(id=dealerId)
- if not dealer.isJosEnable():
- return JsonResponse({"result": 0, "description": u"抱歉,您暂时无法配置此项活动,详情请咨询平台方"})
- # 检查活动的设备类型是否匹配
- onsaleType = onsale.onsaleType
- expression = OnSale.onsaleTypeDict[onsaleType]['expression']
- onsale.onClickUrl = OnSale.onsaleTypeDict[onsaleType]['onClickUrl']
- onsale.showType = OnSale.onsaleTypeDict[onsaleType]['showType']
- if expression:
- for lc in onsale.logicalCodeList:
- dev = Device.get_dev_by_logicalCode(lc)
- if dev is None:
- continue
- if not eval(expression):
- return JsonResponse({'result': 0, 'description': u'编码为:%s的设备类型不符合本次活动的要求,请去掉该设备哦' % lc, 'payload': {}})
- onsale.dealerId = str(request.user.bossId)
- onsale.save()
- return JsonResponse({'result': 1, 'description': '', 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请刷新'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def deleteOnsale(request):
- # type: (WSGIRequest)->JsonResponse
- payload = json.loads(request.body)
- onsaleId = payload.get('id')
- if not onsaleId:
- return JsonErrorResponse(description=u'数据不完整,请刷新')
- obj = OnSale.objects.get(id=onsaleId)
- obj.delete()
- return JsonResponse({'result': 1, 'description': '', 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,删除失败,请您重试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def editOnsale(request):
- # type: (WSGIRequest)->JsonResponse
- payload = json.loads(request.body) if request.body else {}
- if not payload:
- return JsonErrorResponse(description=u'发送的编辑数据为空')
- payload['startTime'] = to_datetime(payload['startTime'] + ' 00:00:00')
- payload['endTime'] = to_datetime(payload['endTime'] + ' 23:59:59')
- obj = OnSale.objects.get(id=payload['id'])
- obj.update(**payload)
- return JsonResponse({'result': 1, 'description': '', 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请刷新'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getOnsaleRecord(request):
- # type: (WSGIRequest)->JsonResponse
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- startTimeStr = request.GET.get('startTime', None)
- if not startTimeStr:
- return JsonErrorResponse(description=u'数据为空,请重试')
- startTime = to_datetime(startTimeStr + ' 00:00:00')
- endTimeStr = request.GET.get('endTime', 10)
- endTime = to_datetime(endTimeStr + ' 23:59:59')
- onsaleId = request.GET.get('onsaleId', None)
- rcds = OnSaleRecord.objects.filter(onsaleId=onsaleId, addedTime__gte=startTime, addedTime__lte=endTime)
- dataList = []
- countDict = {}
- for rcd in rcds:
- data = {'clickTime': rcd.addedTime.strftime(Const.DATETIME_FMT)}
- desc = u'用户:%s,' % rcd.nickName
- if rcd.onsaleDetail.has_key('coins'):
- desc += u' 领取%s个金币' % rcd.onsaleDetail['coins']
- if rcd.onsaleDetail.has_key('duration'):
- desc += u' 启动免费体验%s分钟' % rcd.onsaleDetail['duration']
- if rcd.onsaleDetail.has_key('phoneNumber'):
- desc += u' 手机号码:%s' % rcd.onsaleDetail['phoneNumber']
- data['description'] = desc
- data.update(rcd.onsaleDetail)
- for k, v in rcd.onsaleDetail.items():
- countKey = '%sTotal' % k
- if countDict.has_key(countKey):
- countDict[countKey] += v
- else:
- countDict[countKey] = v
- dataList.append(data)
- return JsonResponse(
- {
- 'result': 1,
- 'description': '',
- 'payload':
- {
- 'total': len(dataList),
- 'dataList': dataList[(pageIndex - 1) * pageSize: pageIndex * pageSize],
- 'countDict': countDict
- }
- })
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'创意文件存储失败,请重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def uploadCreative(request):
- # type: (WSGIRequest)->JsonResponse
- files = request.FILES.getlist('file')
- if not len(files):
- return JsonResponse({'result': 0, 'description': u'未找到上传的创意文件,请重新试试', 'payload': {}})
- uploader = AliOssFileUploader(inputFile=request.FILES.getlist('file')[0], uploadType='creative')
- logger.info('[uploadItemPic] %s is being used' % (repr(uploader),))
- try:
- outputUrl = uploader.upload()
- return JsonResponse({'result': 1, 'description': '', 'payload': outputUrl})
- except InvalidFileSize, e:
- logger.info(
- '%s(id=%s)\'s uploaded file reached limit' % (request.user.__class__.__name__, str(request.user.id),))
- return JsonResponse({'result': 0, 'description': e.message, 'payload': {}})
- except InvalidFileName, e:
- logger.info(
- '%s(id=%s)\'s uploaded file name is not legal' % (request.user.__class__.__name__, str(request.user.id),))
- return JsonResponse({'result': 0, 'description': e.message, 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'状态更新错误,请刷新页面重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def toggleOnsale(request):
- # type: (WSGIRequest)->JsonResponse
- payload = json.loads(request.body)
- status = payload.get('status')
- onsaleId = payload.get('id')
- onsale = OnSale.objects.get(id=onsaleId)
- onsale.status = status
- onsale.save()
- return JsonResponse({'result': 1, 'description': '', 'payload': ''})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取价格失败,请刷新页面重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getPricePerHour(request):
- # type: (WSGIRequest)->JsonResponse
- lc = request.GET.get('logicalCode')
- dev = Device.objects.get(logicalCode=lc)
- return JsonResponse({'result': 1, 'description': '', 'payload': dev.otherConf.get('pricePerHour', 2.0)})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def setBatchDevsSwitch(request):
- # type: (WSGIRequest)->JsonResponse
- data = json.loads(request.body) if request.body else {}
- if not data:
- return JsonErrorResponse(u'数据为空,请重试')
- lcs = data['logicalCodes']
- isFault = data['isFault']
- objs = Device.objects.filter(devNo__in=lcs)
- for obj in objs:
- dev = Device.get_dev(obj.devNo)
- obj.isFault = isFault
- try:
- box = ActionDeviceBuilder.create_action_device(dev)
- box.set_dev_fault(isFault)
- obj.save()
- Device.invalid_device_cache(obj.devNo)
- except Exception as e:
- logger.exception(e)
- continue
- return JsonResponse({"result": 1, "description": "", "payload": {}})
- # 批量设置退费保护时间
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def setBatchRefundProtectionTime(request):
- # type: (WSGIRequest)->JsonResponse
- data = json.loads(request.body) if request.body else {}
- if not data:
- return JsonErrorResponse(u'数据为空,请重试')
- lcs = data['logicalCodes']
- refundProtectionTime = data['refundProtectionTime']
- try:
- Device.objects.filter(devNo__in=lcs).update(refundProtectionTime=refundProtectionTime).select_for_update()
- except Exception as e:
- logger.exception(e)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getCardTicketTypeList(request):
- # type: (WSGIRequest)->JsonResponse
- objs = VirtualCard.objects.filter(ownerId=str(request.user.bossId))
- dataList = []
- for obj in objs:
- # if '*' in obj.groupIDs:
- # groupIds = Group.get_group_ids_of_dealer(str(request.user.id))
- # else:
- # groupIds = obj.groupIds
- data = {
- 'cardName': obj.cardName,
- 'price': obj.price,
- 'groupIds': obj.groupIds,
- 'periodDays': obj.periodDays,
- 'expiredTime': obj.expiredTime.strftime('%Y-%m-%d'),
- 'dayQuota': obj.dayQuota,
- 'quota': obj.quota,
- 'userLimit': obj.userLimit,
- 'userDesc': obj.userDesc,
- 'dealerDesc': obj.dealerDesc
- }
- dataList.append(data)
- return JsonResponse({"result": 1, "description": '', "payload": {'datalist': dataList}})
- @error_tolerate(nil=JsonErrorResponse(u"获取虚拟卡列表失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getCardTicketList(request):
- """
- 经销商 优惠卡卷列表
- 可通过卡名称搜索
- 可通过 售卡状态 卡使用地址进行筛选
- :param request:
- :return:
- """
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- status = request.GET.get("status") # 卡状态
- groupId = request.GET.get("groupId") # 地址ID
- searchKey = request.GET.get("searchKey") # 卡名称
- # 没有传递状态 则是全部的可用状态
- statusList = [int(status)] if status else [0, 1]
- filters = {"ownerId": str(request.user.bossId), "status__in": statusList}
- # 传递了地址的情况 则全选地址的 和单独选择的都要算上
- if groupId:
- filters.update({"groupIds__in": ["*", groupId]})
- objs = VirtualCard.objects.filter(**filters)
- if searchKey:
- objs = objs.search(searchKey, ["cardName"])
- total = objs.count()
- dataList = []
- for obj in objs.skip((pageIndex - 1) * pageSize).limit(pageSize):
- dataList.append(obj.to_dict())
- return JsonResponse({"result": 1, "description": '', "payload": {'total': total, 'pageSize': pageSize, 'dataList': dataList}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'添加失败,请重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def addTicketCard(request):
- def sort_quota(qArray): # type:(list) -> list
- # 首先检查单位是否重复 对于重复的单位叠加处理
- qDict = defaultdict(int)
- for _item in qArray:
- _count, _unit = _item["count"], _item["unit"]
- qDict[_unit] += int(_count)
- if len(qDict) != len(qArray):
- raise ServiceException({"result": 2, "description": u"额度设置错误,额度单位重复"})
-
- return sorted(qArray, key=lambda x: x["unit"])
- if not request.body:
- return JsonErrorResponse(description=u'传入数据为空')
- payload = json.loads(request.body)
- cardId = payload.get("cardId")
- cardName = payload["cardName"]
- userDesc = payload["userDesc"]
- userLimit = int(payload["userLimit"])
- periodDays = float(payload["periodDays"])
- try:
- expiredTime = to_datetime(payload['expiredTime'] + ' 23:59:59')
- except Exception as e:
- expiredTime = to_datetime(payload['expiredTime'])
- devTypeList = payload["devTypeList"]
- groups = ['*'] if payload['groups'] == '*' else [grp['groupId'] for grp in payload['groups']]
- price = RMB(payload["price"])
- power = int(payload["power"])
- try:
- dayQuota = sort_quota(payload["dayQuota"])
- quota = sort_quota(payload["quota"])
- except ServiceException as e:
- return JsonErrorResponse(description=e.result["description"])
- if cardId:
- try:
- card = VirtualCard.objects.get(id=cardId)
- except DoesNotExist:
- return JsonErrorResponse(description=u"编辑虚拟卡卷失败")
- if card.ownerId != str(request.user.bossId):
- return JsonErrorResponse(description=u"保存失败,请重新尝试")
- else:
- card = VirtualCard()
- card.update(
- cardName=cardName, userDesc=userDesc, userLimit=userLimit, periodDays=periodDays,
- expiredTime=expiredTime, devTypeList=devTypeList, groupIds=groups, price=price,
- power=power, dayQuota=dayQuota, quota=quota, ownerId=str(request.user.bossId),
- upsert=True
- )
- return JsonOkResponse()
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'删除失败,请重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def deleteCardTicket(request):
- # type: (WSGIRequest)->JsonResponse
- if not request.body: return JsonErrorResponse(description=u'传入数据为空')
- payload = json.loads(request.body)
- cardId = payload['id']
- try:
- VirtualCard.get_collection().update({'_id': ObjectId(cardId)}, {'$set': {'status':-1}})
- return JsonResponse({"result": 1, "description": "", "payload": {}})
- except Exception as e:
- logger.exception('update error=%s' % e)
- return JsonResponse({"result": 0, "description": u"删除失败,请您稍后重试", "payload": {}})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def switchCardTicket(request):
- # type: (WSGIRequest)->JsonResponse
- if not request.body: return JsonErrorResponse(description=u'传入数据为空')
- payload = json.loads(request.body)
- cardId = payload['id']
- try:
- vCard = VirtualCard.objects.get(id=cardId)
- vCard.status = 1 if vCard.status == 0 else 0
- vCard.save()
- return JsonResponse({"result": 1, "description": "", "payload": {}})
- except Exception as e:
- logger.exception('switchCardTicket error=%s' % e)
- return JsonResponse({"result": 0, "description": u"切换虚拟卡的状态失败,请您刷新页面后重试", "payload": {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'删除失败,请重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def delUserVirtualCard(request):
- payload = json.loads(request.body)
- cardId = payload.get("cardId")
- if not cardId:
- return JsonErrorResponse(description=u"该虚拟卡不存在")
- try:
- vCard = UserVirtualCard.objects.get(id=cardId)
- except DoesNotExist:
- return JsonErrorResponse(description=u"该虚拟卡不存在")
- if vCard.dealerId != str(request.user.id):
- return JsonErrorResponse(u"不是您的虚拟卡,无权删除")
- record = AdjustUserVirtualCardRecord(
- cardId=cardId,
- cardNo=vCard.cardNo,
- beforeAdjust=vCard.expiredTime,
- operator=str(request.user.id),
- dealerId=str(request.user.bossId),
- adjustType=TYPE_ADJUST_USER_VIRTUAL_CARD.DELETE,
- oldQuota=vCard.quota,
- adjustQuota=[{"count": 0, "unit": vCard.quota[0].get("unit")}]
- )
- vCard.delete()
- record.save()
- return JsonOkResponse(description=u"删除成功")
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'调整失败,请重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def adjustUserVirtualCardTime(request):
- payload = json.loads(request.body)
- cardId = payload.get("cardId", "")
- days = int(payload.get("days", 0))
- if not days:
- return JsonErrorResponse(description=u"您调整的时间没有变化")
- if not cardId:
- return JsonErrorResponse(description=u"该虚拟卡不存在")
- try:
- vCard = UserVirtualCard.objects.get(id=cardId)
- except DoesNotExist:
- return JsonErrorResponse(description=u"该虚拟卡不存在")
- if vCard.dealerId != str(request.user.id):
- return JsonErrorResponse(u"不是您的虚拟卡,无权修改")
- record = AdjustUserVirtualCardRecord(
- cardId=cardId,
- cardNo=vCard.cardNo,
- beforeAdjust=vCard.expiredTime,
- operator=str(request.user.id),
- dealerId=str(request.user.bossId),
- adjustType=TYPE_ADJUST_USER_VIRTUAL_CARD.ADJUST_DAYS,
- adjustDays=days,
- oldQuota=vCard.quota,
- adjustQuota=[{"count": 0, "unit": vCard.quota[0].get("unit")}]
- )
- vCard.expiredTime = vCard.expiredTime + datetime.timedelta(days=days)
- vCard.save()
- record.save()
- return JsonOkResponse(description=u"操作成功,虚拟卡{}过期调整过期时间{}天".format(str(vCard.id), days))
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'调整失败,请重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def adjustUserVirtualCardQuota(request):
- """
- 调整虚拟卡额度
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- cardId = payload.get("cardId", "")
- quota = payload.get("quota")
- dayQuota = payload.get("dayQuota")
- if not cardId:
- return JsonErrorResponse(description=u"该虚拟卡不存在")
- if not all([quota, dayQuota]):
- return JsonErrorResponse(description="参数不全")
- try:
- vCard = UserVirtualCard.objects.get(id=cardId)
- except DoesNotExist:
- return JsonErrorResponse(description=u"该虚拟卡不存在")
- vCard.quota = quota
- vCard.dayQuota = dayQuota
- for _item in vCard.quota:
- _item["count"] = float(_item["count"])
- for _item in vCard.dayQuota:
- _item["count"] = float(_item["count"])
- vCard.save()
- return JsonOkResponse(description=u"操作成功,虚拟卡{}调整额度成功")
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"调整失败,请重新试试"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def adjustUserVirtualState(request):
- """
- 修改虚拟卡 的状态 主要是冻结/非冻结 霍珀需求
- 这个操作状态就不放入调整记录了
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- cardId = payload.get("id", "")
- if not cardId:
- return JsonErrorResponse(description=u"该虚拟卡不存在")
- try:
- vCard = UserVirtualCard.objects.get(id=cardId)
- except DoesNotExist:
- return JsonErrorResponse(description=u"该虚拟卡不存在")
- if vCard.status in ["normal", "warning"]:
- vCard.status = "frozen"
- else:
- vCard.status = "normal"
- vCard.save()
- return JsonOkResponse(description=u"操作成功")
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'读取失败,请重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def userVirtualCardAdjustRecord(request):
- pageIndex = int(request.GET.get("pageIndex", 1))
- pageSize = int(request.GET.get("pageSize", 10))
- searchKey = request.GET.get("searchKey")
- _type = request.GET.get("type")
- startTime = request.GET.get("startTime")
- endTime = request.GET.get("endTime")
- matchFilters = {"dealerId": str(request.user.bossId)}
- if _type:
- if _type not in Const.TYPE_ADJUST_USER_VIRTUAL_CARD.choices():
- return JsonErrorResponse(description=u"筛选种类错误,无此相关记录")
- else:
- matchFilters.update({"adjustType": _type})
- if startTime:
- startDataTime = to_datetime(startTime + ' 00:00:00', "%Y-%m-%d %H:%M:%S")
- now = datetime.datetime.now()
- if not endTime:
- endDateTime = now + datetime.timedelta(days=1)
- else:
- endDateTime = to_datetime(endTime, "%Y-%m-%d")
- if endDateTime > now:
- endDateTime = now
- endDateTime = endDateTime + datetime.timedelta(days=1)
- if startDataTime >= endDateTime:
- endDateTime = startDataTime + datetime.timedelta(days=1)
- matchFilters.update(
- {
- "dateTimeAdded": {
- "$gte": startDataTime,
- "$lte": endDateTime
- }
- }
- )
- if searchKey:
- matchFilters.update({
- "cardNo": searchKey
- })
- records = AdjustUserVirtualCardRecord.get_collection().find(
- matchFilters
- ).sort(
- [("dateTimeAdded", -1)]
- ).skip(
- pageSize * (pageIndex - 1)
- ).limit(
- pageSize
- )
- data = []
- for record in records:
- oldQuota = record.get("oldQuota")[0]
- adjustQuota = record.get("adjustQuota")[0]
- newQuota = {
- "count" :oldQuota.get("count") + adjustQuota.get("count"),
- "unit": oldQuota.get("unit")
- }
- dealerId = record.get("operator")
- dealer = Dealer.get_dealer(dealerId)
- operator = dealer.get("nickname") or dealer.get("username")
- data.append(
- {
- "cardId": record.get("cardId"),
- "cardNo": record.get("cardNo"),
- "beforeAdjustExpired": record.get("beforeAdjust").strftime("%Y-%m-%d %H:%M:%S"),
- "afterAdjustExpired": (record.get("beforeAdjust") + datetime.timedelta(days=record.get("adjustDays"))).strftime("%Y-%m-%d %H:%M:%S"),
- "beforeAdjustQuota": "{} {}".format(oldQuota.get("count"), oldQuota.get("unit")),
- "afterAdjustQuota": "{} {}".format(newQuota.get("count"), oldQuota.get("unit")),
- "operator": operator,
- "adjustType": record.get("adjustType"),
- "adjustDate": record.get("dateTimeAdded")
- }
- )
- return JsonOkResponse(payload={"total": 10000, "dataList": data})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'读取失败,请重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getUserCardTicketList(request):
- """
- 经销商获取 已经发售的虚拟卡
- 可以通过卡号搜索
- 可以通过根据发卡地址来筛选 groupId
- 可以通过卡类型筛选 dealerCardTypeId
- 可以通过卡的状态来筛选 status 0(没过期 ) 1(过期)
- :param request:
- :return:
- """
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- searchKey = request.GET.get('searchKey', '')
- dealerCardTypeId = request.GET.get("dealerCardTypeId")
- status = request.GET.get("status")
- groupId = request.GET.get("groupId")
- userId = str(request.GET.get('userId', ''))
- isEmptyCard = int(request.GET.get('isEmptyCard', 0))
- if isEmptyCard:
- objs = VirtualCardBuilder.find_dealer_virtual_card(str(request.user.id)).order_by('-id')
- else:
- filters = {
- "dealerId": str(request.user.bossId)
- }
- # 添加筛选条件
- if userId:
- filters.update({"openIds__contains": userId})
- if groupId:
- filters.update({"groupIds__in": ["*", groupId]})
- if dealerCardTypeId:
- filters.update({"cardTypeId": dealerCardTypeId})
- if status:
- nowTime = datetime.datetime.now()
- status = int(status)
- filters.update({"expiredTime__gt": nowTime}) if status else filters.update({"expiredTime__lt": nowTime})
- objs = UserVirtualCard.objects.filter(**filters).order_by('-startTime')
- if searchKey:
- objs = objs.search(searchKey)
- total = objs.count()
- dataList = []
- for obj in objs.skip((pageIndex - 1) * pageSize).limit(pageSize):
- data = obj.to_dict()
- data.update(obj.quotaInfo)
- dataList.append(data)
- return JsonResponse({"result": 1, "description": '', "payload": {'total': total, 'dataList': dataList}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"读取失败,请重新试试"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getUserCardTicketDetail(request):
- """
- 获取用户的
- :param request:
- :return:
- """
- cardId = request.GET.get("cardId", "")
- try:
- vCard = UserVirtualCard.objects.get(id=cardId)
- except DoesNotExist:
- return JsonErrorResponse(description=u"查询错误,请刷新页面重试")
- data = vCard.to_detail()
- data.update({"frozenState": not vCard.status in ["normal", "warning"]})
- return JsonOkResponse(payload=data)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"备注失败,请重新试试"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def remarkUserVirtual(request):
- """
- 霍珀需求 经销商为已发卡卷添加备注
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- cardId = payload.get("cardId")
- remark = payload.get("remark")
- dealerId = str(request.user.bossId)
- try:
- vCard = UserVirtualCard.objects.get(id=cardId)
- except DoesNotExist:
- return JsonErrorResponse(description=u"虚拟卡备注失败,请刷新页面试试")
- if vCard.dealerId != dealerId:
- return JsonErrorResponse(description=u"不是您的虚拟卡您无权修改")
- vCard.update(remark=remark)
- return JsonOkResponse()
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'读取失败,请重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getElcPriceModList(request):
- dealerId = str(request.user.bossId)
- objs = ElecPriceTemplate.objects.filter(ownerId=dealerId)
- resultList = [{'id': str(obj.id), 'name': obj.name, 'price': obj.priceList} for obj in objs]
- return JsonResponse({"result": 1, "description": '', "payload": resultList})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'保存失败,请重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def saveElcPriceMod(request):
- dealerId = str(request.user.bossId)
- payload = json.loads(request.body)
- priceList = payload['price']
- logicalCode = payload['logicalCode']
- newName = payload.get('name', None)
- dev = Device.get_dev_by_logicalCode(logicalCode)
- group = Group.get_group(dev['groupId'])
- if newName is None:
- newName = group['groupName'] + datetime.datetime.now().strftime('%Y%m%d%H%M%S')
- newObj = ElecPriceTemplate(ownerId=dealerId,
- name=newName,
- priceList=priceList)
- newObj.save()
- return JsonResponse({"result": 1, "description": '', "payload": None})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'保存失败,请重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def saveDeviceElcPrice(request):
- """
- 这个是 用心汽车桩专用的 保存汽车的电价设置
- """
- payload = json.loads(request.body)
- priceList = payload['price']
- logicalCode = payload['logicalCode']
- from apps.web.core.device_define.yongxin import DefaultParams
- if len(priceList) != DefaultParams.DEFAULT_ELEC_PRICE_INTERVAL_NUM:
- return JsonErrorResponse(description=u"电价参数设置错误,请重新试试")
- if filter(lambda x: int(x * 100) > DefaultParams.DEFAULT_MAX_ELEC_PRICE, priceList):
- return JsonErrorResponse(description=u"电价最大为2.55元")
- device = Device.objects.get(logicalCode=logicalCode)
- device.otherConf['priceList'] = priceList
- device.save()
- Device.invalid_device_cache(device.devNo)
- return JsonOkResponse()
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'删除电价失败,请重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def deleteElcPriceMod(request):
- payload = json.loads(request.body)
- ids = [ObjectId(_) for _ in payload['id']]
- ElecPriceTemplate.get_collection().remove({'_id': {'$in': ids}})
- return JsonResponse({"result": 1, "description": '', "payload": None})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'上传的商品图片存储失败,请重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def uploadItemPic(request):
- # type: (WSGIRequest)->JsonResponse
- files = request.FILES.getlist('file')
- if not len(files):
- return JsonResponse({'result': 0, 'description': u'未找到上传的商品图片,请重新试试', 'payload': {}})
- uploader = AliOssFileUploader(inputFile=request.FILES.getlist('file')[0], uploadType='item')
- logger.info('[uploadItemPic] %s is being used' % (repr(uploader),))
- try:
- outputUrl = uploader.upload()
- return JsonResponse({'result': 1, 'description': '', 'payload': outputUrl})
- except InvalidFileSize, e:
- logger.info(
- '%s(id=%s)\'s uploaded file reached limit' % (request.user.__class__.__name__, str(request.user.id),))
- return JsonResponse({'result': 0, 'description': e.message, 'payload': {}})
- except InvalidFileName, e:
- logger.info(
- '%s(id=%s)\'s uploaded file name is not legal' % (request.user.__class__.__name__, str(request.user.id),))
- return JsonResponse({'result': 0, 'description': e.message, 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'编辑商品类型失败,请重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def addEditItemType(request):
- payload = json.loads(request.body)
- ownerId = str(request.user.bossId)
- itemId = payload.get('id', None)
- title = payload.get('name', None)
- desc = payload.get('description', None)
- picUrl = payload.get('img', "")
- price = 100 * payload.get('price')
- try:
- if itemId is not None:
- obj = ItemType.objects.get(id=itemId)
- obj.title, obj.desc, obj.picUrl, obj.price = title, desc, picUrl, price
- obj.save()
- else:
- newObj = ItemType(ownerId=ownerId, title=title, desc=desc, picUrl=picUrl, price=price)
- newObj.save()
- itemId = str(newObj.id)
- except DoesNotExist:
- newObj = ItemType(ownerId=ownerId, title=title, desc=desc, picUrl=picUrl, price=price)
- newObj.save()
- itemId = str(newObj.id)
- except Exception as e:
- logger.exception(e)
- return JsonErrorResponse(description=u'未知错误')
- return JsonResponse({"result": 1, "description": '', "payload": {"id": itemId}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'删除商品类型失败,请重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def deleteItemType(request):
- payload = json.loads(request.body)
- ids = payload.get('ids', [])
- itemIds = [ObjectId(obj) for obj in ids]
- try:
- ItemType.get_collection().remove({'_id': {'$in': itemIds}})
- except Exception as e:
- logger.exception(e)
- return JsonErrorResponse(description=u'未知错误')
- return JsonResponse({"result": 1, "description": '', "payload": None})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取商品类型失败,请重新试试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getItemTypes(request):
- ownerId = str(request.user.bossId)
- itemTypeId = request.GET.get('itemTypeId', '')
- if itemTypeId:
- objs = ItemType.objects.filter(ownerId=ownerId, id=itemTypeId)
- else:
- objs = ItemType.objects.filter(ownerId=ownerId)
- dataList = [{'id': str(obj.id),
- 'name': obj.title,
- 'description': obj.desc,
- 'img': obj.picUrl,
- 'price': float(obj.price) / 100.0} for obj in objs
- ]
- return JsonResponse({"result": 1, "description": '', "payload": {'dataList': dataList}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'编辑格子失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def addEditCell(request):
- payload = json.loads(request.body)
- logicalCode = payload.get('logicalCode')
- cellId = payload.get('id', None)
- cellNo = payload.get('cellNo')
- boardNo = int(payload.get('boardNo'))
- lockNo = int(payload.get('lockNo'))
- itemTitle = payload.get('itemTitle', '')
- itemDesc = payload.get('itemDesc', '')
- itemPicUrl = payload.get('itemPicUrl', '')
- itemPrice = payload.get('itemPrice') * 100
- try:
- if cellId is not None:
- obj = Cell.objects.get(id=cellId)
- obj.cellNo, obj.boardNo, obj.lockNo, obj.itemTitle, obj.itemDesc, obj.itemPicUrl, obj.itemPrice = cellNo, boardNo, lockNo, itemTitle, itemDesc, itemPicUrl, itemPrice
- obj.save()
- else:
- newObj = Cell(logicalCode=logicalCode, cellNo=cellNo, boardNo=boardNo, lockNo=lockNo, itemTitle=itemTitle,
- itemDesc=itemDesc, itemPicUrl=itemPicUrl, itemPrice=itemPrice)
- newObj.save()
- cellId = str(newObj.id)
- except DoesNotExist, e:
- newObj = Cell(logicalCode=logicalCode, cellNo=cellNo, boardNo=boardNo, lockNo=lockNo, itemTitle=itemTitle,
- itemDesc=itemDesc, itemPicUrl=itemPicUrl, itemPrice=itemPrice)
- newObj.save()
- cellId = str(newObj.id)
- except Exception, e:
- return JsonErrorResponse(description=u'未知错误')
- # 重新挂上washConfig套餐信息
- cells = Cell.objects.filter(logicalCode=logicalCode)
- washConfig = {}
- for cell in cells:
- washConfig[str(cell.id)] = {
- 'name': cell.cellNo,
- 'coins': float(cell.itemPrice / 100.0),
- 'price': float(cell.itemPrice / 100.0),
- 'time': 1,
- 'description': cell.itemTitle,
- 'imgList': [cell.itemPicUrl],
- 'unit': u'次'
- }
- dev = Device.get_dev_by_logicalCode(logicalCode)
- dev['washConfig'] = washConfig
- Device.get_collection().update({'devNo': dev['devNo']}, {'$set': {'washConfig': dev['washConfig']}})
- Device.invalid_device_cache(dev['devNo'])
- return JsonResponse({"result": 1, "description": '', "payload": {"id": cellId}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def deleteCell(request):
- payload = json.loads(request.body)
- logicalCode = payload.get('logicalCode')
- cellIds = payload.get('ids')
- Cell.objects(id__in=cellIds).delete()
- # 重新挂上washConfig套餐信息
- cells = Cell.objects.filter(logicalCode=logicalCode)
- washConfig = {}
- for cell in cells:
- washConfig[str(cell.id)] = {
- 'name': cell.cellNo,
- 'coins': float(cell.itemPrice / 100.0),
- 'price': float(cell.itemPrice / 100.0),
- 'time': 1,
- 'description': cell.itemTitle,
- 'imgList': [],
- 'unit': u'次'
- }
- dev = Device.get_dev_by_logicalCode(logicalCode)
- dev['washConfig'] = washConfig
- Device.get_collection().update({'devNo': dev['devNo']}, {'$set': {'washConfig': dev['washConfig']}})
- Device.invalid_device_cache(dev['devNo'])
- return JsonResponse({"result": 1, "description": '', "payload": None})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'查询格子失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getDeviceCells(request):
- logicalCode = request.GET.get('logicalCode')
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 30))
- objs = Cell.objects.filter(logicalCode=logicalCode)
- dev = Device.get_dev_by_logicalCode(logicalCode)
- box = ActionDeviceBuilder.create_action_device(dev)
- lockStatusDict = box.get_all_lock_status()
- dataList = []
- quantity, consumptionQuantity = 0, 0
- for obj in objs:
- dataList.append(
- {
- 'id': str(obj.id), 'cellNo': obj.cellNo, 'boardNo': obj.boardNo,
- 'lockNo': obj.lockNo, 'itemTitle': obj.itemTitle,
- 'itemDesc': obj.itemDesc, 'itemPicUrl': obj.itemPicUrl,
- 'itemPrice': round(obj.itemPrice / 100.0, 2),
- 'lockStatus': lockStatusDict.get(obj.cellNo, 'close'),
- 'quantity': 1 if obj.itemStatus == 'full' else 0
- }
- )
- if obj.itemStatus == 'full':
- quantity += 1
- else:
- consumptionQuantity += 1
- dev['quantity'] = quantity
- dev['consumptionQuantity'] = consumptionQuantity
- Device.update_field(
- dev_no=dev['devNo'],
- update=True,
- quantity=quantity,
- consumptionQuantity=consumptionQuantity)
- return JsonResponse({'result': 1, 'description': '',
- 'payload': {'dataList': dataList[(pageIndex - 1) * pageSize:pageIndex * pageSize]}})
- def openManyCells(dev, strIds):
- ids = [ObjectId(id) for id in strIds]
- cellDict = {}
- cells = Cell.objects.filter(id__in=ids)
- for cell in cells:
- if cellDict.has_key(str(cell.boardNo)):
- cellDict[str(cell.boardNo)].append(cell.lockNo)
- else:
- cellDict[str(cell.boardNo)] = [cell.lockNo]
- box = ActionDeviceBuilder.create_action_device(dev)
- for boardNo, lockNos in cellDict.items():
- try:
- box.open_many_locks(boardNo, lockNos)
- except Exception as e:
- logger.exception(e)
- return JsonResponse({"result": 0, "description": u'打开格子失败', "payload": None})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def addGoodsToDeviceCell(request):
- payload = json.loads(request.body)
- logicalCode = payload['logicalCode']
- dev = Device.get_dev_by_logicalCode(logicalCode)
- openManyCells(dev, payload['ids'])
- ids = [ObjectId(strId) for strId in payload['ids']]
- cells = Cell.objects.filter(id__in=ids)
- for cell in cells:
- cell.itemStatus = 'full'
- try:
- cell.save()
- # 增加一条补货记录
- newStock = StockRecord(
- logicCode=dev['logicalCode'],
- imei=dev['devNo'],
- stockType='add',
- stockTime=datetime.datetime.now().strftime(Const.DATETIME_FMT),
- number=1,
- more="%s:%s" % (cell.cellNo, cell.itemTitle)
- )
- newStock.save()
- except Exception, e:
- continue
- Cell.update_dev_quantity_from_cell(dev)
- return JsonResponse({"result": 1, "description": '', "payload": None})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def unlockCell(request):
- payload = json.loads(request.body)
- logicalCode = payload.get('logicalCode')
- ids = payload.get('id')
- dev = Device.get_dev_by_logicalCode(logicalCode)
- openManyCells(dev, ids)
- return JsonResponse({"result": 1, "description": '', "payload": None})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getDeviceCellsFromDB(request):
- logicalCode = request.GET.get('logicalCode')
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 30))
- objs = Cell.objects.filter(logicalCode=logicalCode)
- dataList = []
- quantity, consumptionQuantity = 0, 0
- for obj in objs:
- dataList.append(
- {'id': str(obj.id), 'cellNo': obj.cellNo, 'boardNo': obj.boardNo,
- 'lockNo': obj.lockNo, 'itemTitle': obj.itemTitle,
- 'itemDesc': obj.itemDesc, 'itemPicUrl': obj.itemPicUrl,
- 'itemPrice': round(obj.itemPrice / 100.0, 2),
- # 'lockStatus':lockStatusDict.get(obj.cellNo,'close'),
- 'quantity': 1 if obj.itemStatus == 'full' else 0}
- )
- if obj.itemStatus == 'full':
- quantity += 1
- else:
- consumptionQuantity += 1
- # TODO 为啥这两个参数只打内存,不更新到数据库
- Device.get_and_update_device_cache(
- dev_no=Device.get_dev_by_logicalCode(logicalCode)['devNo'],
- quantity=quantity,
- consumptionQuantity=consumptionQuantity)
- return JsonResponse({'result': 1, 'description': '',
- 'payload': {'dataList': dataList[(pageIndex - 1) * pageSize:pageIndex * pageSize]}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'获取列表失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getOfflineTaskList(request):
- # type: (WSGIRequest)->JsonResponse
- current_user = request.user # type: Dealer
- page_index = int(request.GET.get('pageIndex', 1))
- page_size = int(request.GET.get('pageSize', 10))
- search_key = request.GET.get('searchKey', None)
- tasks = OfflineTask.objects(ownerId=current_user.id,
- role=current_user.role).search(search_key).order_by('-dateTimeAdded')
- total = tasks.count()
- return JsonOkResponse(
- payload={
- 'dataList': [t.to_dict() for t in tasks.paginate(pageSize=page_size, pageIndex=page_index)],
- 'total': total
- })
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def exportBusinessStats(request):
- """
- 经销商的手机 导出报表
- :param request:
- :return:
- """
- dealer = request.user # type: Dealer
- request_get = request.GET.copy()
- if 'kind' not in request_get:
- request_get['kind'] = 'income'
- if 'time' in request_get and (('startTime' not in request_get) or ('endTime' not in request_get)):
- # 将月份转换成开始时间为1号,结束时间为当月最后一天,因为需要一个前闭后闭区间,所以最后一天日期减一天
- request_get['startTime'] = datetime.datetime.strptime(request_get.pop('time')[0], "%Y-%m")
- request_get['endTime'] = request_get['startTime'] + relativedelta(months=1) - datetime.timedelta(days=1)
- request_get['startTime'] = request_get['startTime'].strftime(Const.DATE_FMT)
- request_get['endTime'] = request_get['endTime'].strftime(Const.DATE_FMT)
- query = prepare_query(request_get) # type: Query
-
- def get_offline_task_name(task_type, user, **kwargs):
- # type: (basestring, Dealer, Dict)->basestring
- type_desc_map = {
- 'income': u'收益',
- 'consume': u'消费',
- 'monthly_bill': u'月度'
- }
- tmp_list = [task_type, type_desc_map.get(kwargs['kind']), user.username]
- if 'logicalCode' in kwargs:
- tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],))
- if 'groupId' in kwargs:
- address = Group.get_group(kwargs['groupId']).get('address', '')
- tmp_list.append(u'地址_%s' % (address,))
- if 'source' in kwargs:
- kind = kwargs.get('kind')
- if kind == 'income':
- source_translation = DEALER_INCOME_SOURCE_TRANSLATION.get(kwargs['source'])
- elif kind == 'consume':
- source_translation = DEALER_CONSUMPTION_AGG_KIND_TRANSLATION.get(kwargs['source'])
- else:
- source_translation = None
- if source_translation:
- tmp_list.append(source_translation)
- tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime']))
- tmp_list.append(str(utils_datetime.generate_timestamp_ex()))
- return '-'.join(tmp_list).replace("/", "_")
- # 此处生成的是 报表文件的名称
- offline_task_name = get_offline_task_name(
- task_type=OfflineTaskType.BUSINESS_REPORT,
- user=dealer,
- **query.raw)
- file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name,
- process_func_name='generate_business_stats_report_by_dealer',
- task_type=OfflineTaskType.BUSINESS_REPORT,
- userid=str(dealer.id),
- role=ROLE.dealer)
- queryAttrs = query.attrs
- queryAttrs['dateTimeAdded__lte'] = dt_to_timestamp(queryAttrs['dateTimeAdded__lte'])
- queryAttrs['dateTimeAdded__gte'] = dt_to_timestamp(queryAttrs['dateTimeAdded__gte'])
- queryAttrs['dealerId'] = str(dealer.id)
- task_caller(func_name=offline_task.process_func_name,
- offline_task_id=str(offline_task.id),
- filePath=file_path,
- queryAttrs=queryAttrs)
- return JsonOkResponse(payload=str(offline_task.id))
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def exportAllTicketList(request):
- """
- 经销商的下的所以虚拟卡
- :param request:
- :return:
- """
- dealer = request.user # type: Dealer
- timeStr = arrow.now().format('YYYY-MM-DD_HH:mm:ss')
- offline_task_name = '已发虚拟卡_{}_{}_{}'.format(dealer.username, timeStr, random.randint(100000, 999999))
- file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name,
- process_func_name='export_vcard_info_excel_from_db',
- task_type=OfflineTaskType.BUSINESS_REPORT,
- userid=str(dealer.id),
- role=ROLE.dealer)
- queryDict = {}
- queryDict['dealerId'] = str(dealer.id)
- task_caller(func_name=offline_task.process_func_name,
- offline_task_id=str(offline_task.id),
- filepath=file_path,
- queryDict=queryDict)
- return JsonOkResponse(payload=str(offline_task.id))
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取收益列表失败"))
- @permission_required(ROLE.dealer)
- def getGroupUserAccountInfo(request):
- """
- 经销商下所有地址的用户充值,消费,余额情况
- """
- dealer = request.user # type: Dealer
- def get_offline_task_name(task_type, user, **kwargs):
- # type: (basestring, Dealer, Dict)->basestring
- tmp_list = [task_type, user.username]
- if 'logicalCode' in kwargs and kwargs['logicalCode']:
- tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],))
- if 'groupId' in kwargs and kwargs['groupId']:
- address = Group.get_group(kwargs['groupId']).get('address', '')
- tmp_list.append(u'地址_%s' % (address,))
- tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime']))
- tmp_list.append(str(utils_datetime.generate_timestamp_ex()))
- return '-'.join(tmp_list).replace("/", "_")
- query_dict = {
- 'startTime': request.GET.get('startTime', '') + ' 00:00:00',
- 'endTime': request.GET.get('endTime', '') + ' 23:59:59',
- 'ownerId': str(dealer.id)
- }
- offline_task_name = get_offline_task_name(
- task_type=u'地址用户充值消费情况统计报表',
- user=dealer,
- **query_dict)
- file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name,
- process_func_name='export_group_user_account_excel_form_db',
- task_type=OfflineTaskType.BUSINESS_REPORT,
- userid=str(dealer.id),
- role=ROLE.dealer)
- task_caller(func_name=offline_task.process_func_name,
- offline_task_id=str(offline_task.id),
- filepath=file_path,
- queryDict=query_dict)
- return JsonResponse({
- 'result': 1,
- 'description': u"请前往离线任务查看任务处理情况",
- 'payload': str(offline_task.id)})
-
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getOfflineTaskStatus(request):
- # type: (WSGIRequest)->JsonResponse
- """
- :param request:
- :return:
- """
- task_id = request.GET.get('id')
- if not task_id:
- return JsonErrorResponse(description=u'查询ID为空')
- task = OfflineTask.objects(id=str(task_id)).get() # type: OfflineTask
- return JsonOkResponse(payload=task.status)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getSubAccountList(request):
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- subaccounts = SubAccount.objects.filter(bossId=str(request.user.bossId))
- total = subaccounts.count()
- dataList = []
- for obj in subaccounts.skip((pageIndex - 1) * pageSize).limit(pageSize):
- if obj.bossId == str(obj.id):
- continue
- dataList.append({
- 'username': obj.username,
- 'permissionList': obj.permissionList,
- 'nickname': obj.nickname,
- 'id': str(obj.id)
- })
- return JsonOkResponse(payload={'agentId': request.user.agentId, 'dataList': dataList, 'total': total})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def addEditSubAccount(request):
- bossId = request.user.bossId
- payload = json.loads(request.body)
- strId = payload.get('id', None)
- if strId is None:
- username = payload['username']
- code = payload['code']
- status, desc = dealerRegisterSMSProvider.verify(username, code)
- if not status:
- return JsonErrorResponse(desc)
- count = SubAccount.objects.filter(username=username, bossId=str(bossId)).count()
- if count > 0:
- return JsonResponse({"result": 0, "description": u'该手机号已经是子账号了,不允许重复配置该手机号为子账号', "payload": None})
- password = payload['password']
- if (not password) or len(password) < 6:
- return JsonResponse({"result": 0, "description": u'必须输入密码,密码长度不能小于6', "payload": None})
- nickname = payload['nickname']
- if not nickname:
- return JsonResponse({"result": 0, "description": u'必须配置昵称', "payload": None})
- newObj = SubAccount(
- username=username,
- nickname=nickname,
- password=make_password(password),
- permissionList=payload.get('permissionList', []),
- agentId=request.user.agentId,
- bossId=bossId
- )
- newObj.save()
- return JsonOkResponse(payload={'id': str(newObj.id)})
- else:
- username = payload['username']
- try:
- obj = SubAccount.objects.get(id=strId)
- except DoesNotExist:
- return JsonResponse({"result": 0, "description": u'并未找到该子账号,可能已经被删除了', "payload": None})
- password = payload['password']
- if (not password) or len(password) < 6:
- return JsonResponse({"result": 0, "description": u'必须输入密码,密码长度不能小于6', "payload": None})
- nickname = payload['nickname']
- if not nickname:
- return JsonResponse({"result": 0, "description": u'必须配置昵称', "payload": None})
- obj.username = username
- obj.nickname = nickname
- obj.permissionList = payload.get('permissionList', [])
- obj.save()
- obj.set_password(password)
- return JsonOkResponse(payload={'id': str(obj.id)})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def deleteSubAccount(request):
- payload = json.loads(request.body)
- idsTemp = payload.get('ids', [])
- ids = [ObjectId(_) for _ in idsTemp]
- SubAccount.objects.filter(id__in=ids).delete()
- return JsonResponse({"result": 1, "description": '', "payload": None})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getAccountPermission(request):
- # 授权经销商用户
- if check_role(request.user, ROLE.dealer):
- permissions = hasattr(request, 'permissions') and getattr(request, 'permissions') # type: dict
- if permissions:
- permissions.update({'role': 'dealerWorker'})
- return JsonOkResponse(payload=permissions)
- # 获取经销商或者子账号所属经销商权限
- mainMenu, homepageData = request.user.myBoss.query_home_page_layout()
- # 调整子账号权限
- if check_role(request.user, ROLE.subaccount):
- for pm in request.user.permissionList:
- if pm in ['today_income', 'today_pay_income', 'today_ad_income', 'offline_coins']:
- homepageData[pm] = True
- else:
- mainMenu[pm] = True
-
- leftHomepage = list(set(Const.HOME_PAGE_DATA_LIST.keys()) - set(request.user.permissionList))
- for pm in leftHomepage:
- homepageData[pm] = False
-
- leftMainmenu = list(set(Const.MAIN_MENU_LIST.keys()) - set(request.user.permissionList))
- for pm in leftMainmenu:
- mainMenu[pm] = False
- return JsonOkResponse(payload={'role': request.user.role, 'homepageData': homepageData, 'mainMenu': mainMenu})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'操作失败'))
- @permission_required(ROLE.dealer)
- def getAccountPermissionById(request):
- strId = request.GET.get('id', None)
- subList = SubAccount.objects.get(id=strId).permissionList
- mainMenu, homepageData = request.user.query_home_page_layout()
- for menu, value in mainMenu.iteritems():
- if not value:
- continue
- if menu in subList:
- mainMenu[menu] = True
- else:
- mainMenu[menu] = False
- mainMenu['sim_card'] = False # sim卡充值不允许给子账号操作
- for menu, value in homepageData.iteritems():
- if not value:
- continue
- if menu in subList:
- homepageData[menu] = True
- else:
- homepageData[menu] = False
- return JsonOkResponse(payload={'homepageData': homepageData, 'mainMenu': mainMenu})
- @permission_required(ROLE.dealer)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试'))
- def subAccountRegisterCode(request):
- # type: (WSGIRequest)->JsonResponse
- payload = json.loads(request.body)
- phoneNumber = payload.get('username', None)
- agent = Agent.get_agent(request.user.agentId)
- productName = agent['productName']
- if not phoneNumber:
- return JsonResponse({'result': 0, 'description': u'手机号码为空'})
- if len(SubAccount.objects.filter(username=phoneNumber, bossId=str(request.user.id))):
- return JsonResponse({'result': 0, 'description': u'该手机号已经是您的子账号了'})
- status, msg = dealerRegisterSMSProvider.get(phoneNumber=phoneNumber,
- productName=productName,
- vendor=SysParas.get_sms_vendor(request.user.smsVendor))
- if not status:
- return JsonResponse({'result': 0, 'description': msg})
- else:
- return JsonResponse({'result': 1, 'description': ''})
- @permission_required(ROLE.dealer)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试'))
- def saveAccountPermission(request):
- payload = json.loads(request.body)
- subId = payload.get('id')
- homepageData = payload.get('homepageData', [])
- mainMenu = payload.get('mainMenu', [])
- obj = SubAccount.objects.get(id=subId)
- perList = []
- for k, v in homepageData.items():
- if v:
- perList.append(k)
- for k, v in mainMenu.items():
- if v:
- perList.append(k)
- obj.permissionList = perList
- obj.save()
- return JsonResponse({'result': 1, 'description': ''})
- @permission_required(ROLE.dealer)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试'))
- def getAlarmList(request):
- # type: (WSGIRequest)->JsonResponse
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- queryset = FaultRecord.objects(dealerId=str(request.user.id), status=FAULT_RECORD_STATUS.INIT).order_by('-createdTime')
- records = queryset.paginate(pageIndex=pageIndex, pageSize=pageSize) # type: Iterable[FaultRecord]
- total = queryset.count()
- return JsonOkResponse(payload={'dataList': [ _.to_dict() for _ in records ], 'total': total})
- @permission_required(ROLE.dealer)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试'))
- def handleAlarm(request):
- # type: (WSGIRequest)->JsonResponse
- payload = json.loads(request.body)
- id_ = payload.get('id')
- if id_ is None:
- return JsonErrorResponse(description=u'id未传入')
- status = payload.get('status')
- if status is None:
- return JsonErrorResponse(description=u'处理状态未传入')
- dealedDetail = payload.get("dealedDetail", "")
- if type(id_) == list:
- id_list = id_
- else:
- id_list = [id_]
- for item_id in id_list:
- alarm = FaultRecord.objects(id=item_id).get() # type: FaultRecord
- alarm.set_status(status=status, dealedDetail=dealedDetail)
- if status == "handled":
- task_caller(
- "send_to_xf_fault_handle",
- devNo=alarm.imei,
- faultId=str(alarm.id)
- )
- handler_event_to_zhejiang(id_list[0])
- dev = Device.get_dev(alarm.imei)
- box = ActionDeviceBuilder.create_action_device(dev)
- if box.isHaveFaultHandle:
- try:
- box.faultHandle(alarm=alarm)
- except:
- pass
- return JsonOkResponse()
- @permission_required(ROLE.dealer)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试'))
- def checkAlarm(request):
- # type: (WSGIRequest)->JsonResponse
- id_ = request.GET.get('id')
- if id_ is None:
- return JsonErrorResponse(description=u'id未传入')
- alarm = FaultRecord.objects(id=id_).get() # type: FaultRecord
- dev = Device.get_dev(alarm.imei)
- box = ActionDeviceBuilder.create_action_device(dev)
- try:
- desc = box.check_alarm(alarm)
- except ServiceException , e:
- return JsonResponse({"result": 0, "description": e.result.get('description'), 'payload': {}})
- except Exception, e:
- return JsonResponse({"result": 0, "description": u'系统异常,检查告警失败', 'payload': {}})
- return JsonResponse({"result": 1, "description": desc, 'payload': {}})
- @permission_required(ROLE.dealer)
- @error_tolerate(logger = logger, nil = JsonErrorResponse(u'系统错误,请稍后再试'))
- def withdrawEntry(request):
- # type: (WSGIRequest)->JsonResponse
- user = request.user # type: Dealer
- if not check_role(user, ROLE.dealer):
- return ErrorResponseRedirect(error = u'权限错误')
- # 检查是否有非法订单,如果有,不允许提现直接返回错误
- if RechargeRecord.have_illegal_order(str(user.id), user.maxPackagePrice):
- return ErrorResponseRedirect(error = u'系统检测到部分存疑订单,暂时不能提现。请联系平台客服确认')
- source_key = request.GET.get('sourceId')
- if not WithdrawGateway.is_ledger(source_key):
- return ErrorResponseRedirect(error = u'系统配置错误,请联系平台客服(10003)')
- source_type = request.GET.get('sourceType')
- assert source_type in DEALER_INCOME_TYPE.choices(), 'invalid dealer income type'
- if source_key not in user.balance_dict(source_type):
- return ErrorResponseRedirect(error = u'提现参数错误,请刷新后重试')
- is_ledger, agent, withdraw_gateway_list = Agent.withdraw_gateway_list(source_key)
- if not is_ledger:
- return ErrorResponseRedirect(error = u'系统配置错误,请联系平台客服(10005)')
- wechat_withdraw_gateway = withdraw_gateway_list['wechat'] # type: WithdrawGateway
- if wechat_withdraw_gateway.support_withdraw and not wechat_withdraw_gateway.manual_withdraw:
- code = request.GET.get('code', None)
- if not code:
- redirect = request.GET.get('redirect')
- return ExternalResponseRedirect(
- WechatAuthBridge(wechat_withdraw_gateway.app).generate_auth_url_base_scope(
- concat_server_end_url(
- uri = '/dealer/withdraw/entry?sourceType={source_type}&sourceId={source_key}'.format(
- source_type = source_type,
- source_key = source_key
- )), payload = base64.b64encode(redirect)))
- else:
- auth_bridge = WechatAuthBridge(wechat_withdraw_gateway.app)
- openId = auth_bridge.authorize(code)
- if openId is not None:
- redirect = base64.b64decode(request.GET.get('payload'))
- redirect = add_query(redirect, {
- 'sourceType': source_type,
- 'sourceId': source_key,
- 'openId': openId
- })
- return FrontEndResponseRedirect(redirect)
- else:
- return ErrorResponseRedirect(error = u'微信授权失败,请刷新后重试')
- else:
- redirect = request.GET.get('redirect')
- redirect = add_query(redirect, {
- 'sourceType': source_type,
- 'sourceId': source_key,
- 'openId': ''
- })
- return FrontEndResponseRedirect(redirect)
- @permission_required(ROLE.dealer)
- def ActivateUser(request):
- """
- 安骑的 用户缴纳金额后 经销商激活
- 需要查询对应的 推荐人,如果存在推荐人,将其金币数量增加固定数量
- """
- user = request.user
- payload = json.loads(request.body)
- _id = payload.get("id", "") # 存有用户激活信息的ID
- status = payload.get("status", "")
- remarks = payload.get("remarks", "")
- groupIds = Group.get_group_ids_of_dealer(str(user.id)) # 获取该经销商下的所有的groupId
- customer = MyUser.objects.get(id=_id)
- if int(status) == 2: # 2表示用户信息激活状态为成功
- MyUser.set_active_info(
- {"isMember": True,
- "status": status,
- "remarks": remarks},
- openId=customer.openId,
- agentId=customer.agentId,
- groupId__in=groupIds
- )
- # TODO zjl 这一部分任务查询时间任过长,没有索引, 是否考虑设置异步任务触发
- recommender = MyUser.get_active_info(openId=customer.openId, agentId=customer.agentId, groupId__in=groupIds).get("recommender") # 推荐人
- if recommender:
- groupList = Group.get_groups_of_dealer(user.id)
- recommender = MyUser.objects.get(phoneNumber=recommender)
- if recommender.groupId not in groupList: # 添加对于当前的recommender的验证 要是同一个经销商下的
- logger.info("uninvalid recommender dealer=%s, recommender=%s" % (user.nickname, recommender.nickname))
- else:
- coins = 10 # TODO zjl 添加推荐人金币 金币设置值
- update = recommender.incr_balance(VirtualCoin(coins))
- if not update:
- logger.info("recommender %s get coins faild." % recommender.nickname)
- else:
- # 添加一条充值记录
- orderNo = str(uuid.uuid1())
- try:
- newRcd = RechargeRecord(orderNo=orderNo,
- coins=coins,
- money=0.00,
- openId=recommender.openId,
- wxOrderNo=u'活动赠币',
- nickname=recommender.nickname,
- result='success',
- via='sendcoin',
- operator=str(user.id))
- newRcd.save()
- except Exception as e:
- logger.exception('update record for feedback coins error=%s,orderNo=%s' % (e, orderNo))
- return JsonOkResponse(u"会员录入成功,可以正常使用换电柜")
- elif int(status) == 3: # 3表示用户信息激活状态为失败
- MyUser.set_active_info(
- {"isMember": False,
- "status": status,
- "remarks": remarks,
- "auditTime": datetime.datetime.strftime(datetime.datetime.now(), "%Y-%m-%d %H:%M:%S")},
- openId=customer.openId,
- agentId=customer.agentId,
- groupId__in=groupIds
- )
- return JsonOkResponse(u"已拒绝该用户")
- else:
- logger.error("uninvalid status : %s" % status)
- return JsonErrorResponse(u"无效的审核状态")
- @permission_required(ROLE.dealer)
- def delUserActiveInfo(request):
- user = request.user
- payload = json.loads(request.body)
- ids = payload.get("ids", "")
- # 删除该经销商下的该用户的激活信息
- customers = MyUser.objects.filter(id__in=ids)
- groupIds = Group.get_group_ids_of_dealer(str(user.id))
- for customer in customers:
- MyUser.del_active_info(
- openId=customer.openId,
- agentId=customer.agentId,
- groupId__in=groupIds
- )
- return JsonOkResponse()
- @permission_required(ROLE.dealer)
- def getUserIdentifyList(request):
- """
- 获取临时用户 待激活用户
- """
- pageIndex = int(request.GET.get("pageIndex", 1))
- pageSize = int(request.GET.get("pageSize", 10))
- searchKey = request.GET.get("searchKey")
- status = request.GET.get("status")
- if status in ("", "null"):
- statusList = [0, 1, 2, 3]
- else:
- statusList = [int(status)]
- groupList = Group.get_group_ids_of_dealer(request.user.id)
- query = {
- "groupId": {"$in": groupList},
- "extra.active.status": {"$in": statusList}
- }
- if searchKey:
- query.update(search_query(['nickname', 'phoneNumber'], searchKey).to_query(MyUser))
- results = MyUser.get_collection().find(
- query,
- {
- "nickname": 1,
- "openId": 1,
- "phoneNumber": 1,
- "avatar": 1,
- "extra.active": 1
- }
- ).skip(
- (pageIndex - 1) * pageSize
- ).limit(
- pageSize
- )
- tempUsers = []
- for user in results:
- userDict = dict()
- userDict["id"] = str(user["_id"])
- # userDict["phoneNumber"] = user["phoneNumber"]
- userDict["userNickname"] = user.get("nickname", "")
- userDict["avatarUrl"] = user.get("avatar", "")
- userDict.update(
- user["extra"]["active"]
- )
- tempUsers.append(userDict)
- data = {
- "page": pageIndex,
- # "total": 2 * pageSize if len(tempUsers) >= pageSize else pageSize,
- "total": 10000,
- "pageSize": pageSize,
- "offset": 0,
- "dataList": tempUsers
- }
- return JsonResponse({'result': 1, 'description': "", 'payload': data})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'鉴权失败,请重新登录'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def info(request):
- user = request.user
- payload = {
- 'roles':['admin'],
- 'introduction':user.description,
- 'avatar':user.wechatAuthUserInfo.get('avatar'),
- 'name':user.phone
- }
- return JsonResponse({'result': 1, 'description': '', 'payload':payload})
- def getDashboard(request):
- dealerId = str(request.user.id)
- groupIds = Group.get_group_ids_of_dealer(dealerId)
- devList = Device.get_devices_by_group(groupIds).values()
- devCount = len(devList)
- todayTime = datetime.datetime.now()
- yesterdayTime = todayTime - datetime.timedelta(days=1)
- today = todayTime.strftime(Const.DATE_FMT)
- yesterDay = yesterdayTime.strftime(Const.DATE_FMT)
- rcds = DealerDailyStat.get_collection().find({'dealerId':ObjectId(dealerId), 'date':today}, {'daily':1, 'activedDevRatio':1})
- if rcds.count() == 0:
- todayIncome = 0
- todayRechargeIncome = 0
- todayChargeCardIncome = 0
- todayOrder = 0
- else:
- info = rcds[0]
- todayIncome = info.get('daily', {}).get('totalIncome', 0)
- income = info.get('daily', {}).get('income', {})
- todayRechargeIncome = income.get('recharge', 0)
- todayChargeCardIncome = RMB(income.get('chargeCard', 0)) + RMB(income.get('chargeVirtualCard', 0))
- todayOrder = info.get('daily', {}).get('totalIncomeCount', 0)
- rcds = DealerDailyStat.get_collection().find({'dealerId':ObjectId(dealerId), 'date':yesterDay}, {'daily':1, 'activedDevRatio':1})
- if rcds.count() == 0:
- yesterdayIncome = 0
- yesterdayOrder = 0
- yesterdayActiveDevicePercent = 0
- yesterdayActiveDevice = 0
- yesterdayRechargeIncome = 0
- yesterdayChargeCardIncome = 0
- else:
- info = rcds[0]
- yesterdayIncome = info.get('daily', {}).get('totalIncome', 0)
- income = info.get('daily', {}).get('income', {})
- yesterdayRechargeIncome = income.get('recharge', 0)
- yesterdayChargeCardIncome = RMB(income.get('chargeCard', 0)) + RMB(income.get('chargeVirtualCard', 0))
- yesterdayOrder = info.get('daily', {}).get('totalIncomeCount', 0)
- yesterdayActiveDevicePercent = info.get('activedDevRatio', 0)
- yesterdayActiveDevice = int(round(yesterdayActiveDevicePercent / 100.0 * devCount, 2))
- date = MONTH_DATE_KEY.format(year=todayTime.year, month=todayTime.month)
- rcds = DealerMonthlyStat.get_collection().find({'dealerId':ObjectId(dealerId), 'date':date}, {'monthly':1, 'activedDevRatio':1, 'addedUserCount':1})
- if rcds.count() == 0:
- monthIncome = 0
- monthRechargeIncome = 0
- monthChargeCardIncome = 0
- thisMonthOrder = 0
- userCountAddedThisMonth = 0
- else:
- info = rcds[0]
- monthIncome = info.get('monthly', {}).get('totalIncome', 0)
- income = info.get('monthly', {}).get('income', {})
- monthRechargeIncome = income.get('recharge', 0)
- monthChargeCardIncome = RMB(income.get('chargeCard', 0)) + RMB(income.get('chargeVirtualCard', 0))
- thisMonthOrder = info.get('monthly', {}).get('totalIncomeCount', 0)
- userCountAddedThisMonth = info.get('addedUserCount', 0)
- userCount = request.user.userCount
- return JsonOkResponse(
- payload={
- "todayIncome":todayIncome,
- 'todayRechargeIncome':todayRechargeIncome,
- 'todayChargeCardIncome':todayChargeCardIncome,
- "yesterdayIncome":yesterdayIncome,
- 'yesterdayRechargeIncome':yesterdayRechargeIncome,
- 'yesterdayChargeCardIncome':yesterdayChargeCardIncome,
- "thisMonthIncome": monthIncome,
- 'thisMonthRechargeIncome':monthRechargeIncome,
- 'thisMonthChargeCardIncome':monthChargeCardIncome,
- "todayOrder": todayOrder,
- "yesterdayOrder":yesterdayOrder,
- "thisMonthOrder":thisMonthOrder,
- "deviceTotal":len(devList),
- "yesterdayActiveDevice":yesterdayActiveDevice,
- "yesterdayActiveDevicePercent":yesterdayActiveDevicePercent,
- 'userCount':userCount,
- 'userCountAddedThisMonth':userCountAddedThisMonth
- }
- )
- def deviceOfflineTrend(request):
- dealerId = str(request.user.id)
- todayTime = datetime.datetime.now()
- startTime = todayTime - datetime.timedelta(days=7)
- startDay = startTime.strftime(Const.DATE_FMT)
- endDay = todayTime.strftime(Const.DATE_FMT)
- rcds = DealerDailyStat.get_collection().find({'dealerId':ObjectId(dealerId), 'date':{'$gte':startDay, '$lte':endDay}}, {'other':1, 'date':1})
- dataList = []
- for rcd in rcds:
- other = rcd.get('other', {'totalOfflineTime':0, 'totalOfflineBusyTime':0, 'totalOnlineTime':0})
- totalTime = other['totalOfflineTime'] + other['totalOfflineBusyTime'] + other['totalOnlineTime']
- dataList.append({
- 'dateStr':rcd['date'],
- 'offlineTimePercent':round(100 * other['totalOfflineTime'] / totalTime, 2) if totalTime else 0
- })
- return JsonOkResponse(payload={'dataList': dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def deviceActiveTrend(request):
- dealerId = str(request.user.id)
- todayTime = datetime.datetime.now()
- startTime = todayTime - datetime.timedelta(days=7)
- startDay = startTime.strftime(Const.DATE_FMT)
- endDay = todayTime.strftime(Const.DATE_FMT)
- rcds = DealerDailyStat.get_collection().find({'dealerId':ObjectId(dealerId), 'date':{'$gte':startDay, '$lte':endDay}}, {'activedDevRatio':1, 'date':1})
- dataList = []
- for rcd in rcds:
- ratio = rcd.get('activedDevRatio', 0)
- dataList.append({
- 'dateStr':rcd['date'],
- 'activeDevicePercent':ratio
- })
- return JsonOkResponse(payload={'dataList': dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getGroupStatistics(request):
- def calc_group_stats(groupId, startDate, endDate):
- groupResult = GroupReport.get_rpt([groupId], startDate, endDate)
- offlineCoin = groupResult[groupId].get('lineCoins', 0)
- rcds = GroupDailyStatsModelProxy.get_data_list(startTime=startDate,
- endTime=endDate,
- groupId=ObjectId(groupId),
- only={
- 'other': 1, 'incomeTotal': 1, 'daily': 1,
- 'activedDevRatio': 1
- })
- orderTotal, payIncome, offlineTime, totalTime, totalActivedRate, peakValue = 0, RMB(0.0), 0, 0, 0, 0
- count = 0
- for rcd in rcds:
- count += 1
- daily = rcd.get('daily') or {}
- other = rcd.get('other') or {}
- orderTotal += daily.get('totalIncomeCount', 0)
- payIncome += daily.get('totalIncome', 0)
- offlineTime += other.get('totalOfflineTime', 0)
- totalTime = totalTime + other.get('totalOfflineTime', 0) + other.get('totalOnlineTime', 0) + other.get(
- 'totalOfflineBusyTime', 0)
- totalActivedRate += rcd.get('activedDevRatio', 0)
- dayPeakValue = rcd.get('peakUsage', 0)
- if peakValue <= dayPeakValue:
- peakValue = dayPeakValue
- return {
- 'orderTotal': orderTotal,
- 'payIncome': payIncome,
- 'offlineCoin': offlineCoin,
- 'deviceOfflineCount': int(round(offlineTime / totalTime * 100.0, 2)) if totalTime > 0 else 0,
- # 前台修改后,用设备离线时间占比offlineTime/totalTime * 100
- 'dailyActivityRate': int(round(totalActivedRate / count, 2)) if count > 0 else 0,
- 'peakValue': peakValue
- }
- ownerId = str(request.user.id)
- startDate = str(request.GET.get('startTime'))
- endDate = str(request.GET.get('endTime'))
- pageIndex = int(request.GET.get('pageIndex'))
- pageSize = int(request.GET.get('pageSize'))
- groupIds = Group.get_group_ids_of_dealer(ownerId)
- total = len(groupIds)
- pageGroupIds = groupIds[(pageIndex - 1) * pageSize:pageIndex * pageSize]
- dataList = []
- count = 0
- for groupId in pageGroupIds:
- count += 1
- group = Group.get_group(groupId)
- devList = Device.get_devices_by_group([groupId]).values()
- devCount = len(devList)
- valueDict = calc_group_stats(groupId, startDate, endDate)
- dataList.append({
- 'id':str(groupId),
- 'groupName':group['groupName'],
- 'address':group['address'],
- 'deviceTotal':devCount,
- 'orderTotal':valueDict.get('orderTotal', 0),
- 'payIncome':valueDict.get('payIncome', RMB(0.0)),
- 'offlineCoin':valueDict.get('offlineCoin', 0),
- 'deviceOfflineCount':valueDict.get('deviceOfflineCount', 0),
- 'dailyActivityRate':valueDict.get('dailyActivityRate', 0),
- 'peakValue':valueDict.get('peakValue', 0)
- })
- return JsonOkResponse(payload={'total':total, 'dataList': dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getOrderTrendByGroup(request):
- groupId = request.GET.get('id')
- todayTime = datetime.datetime.now()
- startDate = request.GET.get('startTime', '')
- if not startDate:
- startTime = todayTime - datetime.timedelta(days=7)
- startDate = startTime.strftime(Const.DATE_FMT)
- endDate = request.GET.get('endTime', '')
- if not endDate:
- endDate = (todayTime + datetime.timedelta(days=1)).strftime(Const.DATE_FMT)
- group_report_dict = GroupReport.get_rpt([groupId], startDate, endDate)
- rcds = GroupDailyStatsModelProxy.get_data_list(startTime=startDate,
- endTime=endDate,
- groupId=ObjectId(groupId),
- only={
- 'daily': 1, 'date': 1
- })
- dataList = []
- for rcd in rcds: # type: GroupDailyStat
- daily = rcd.daily
- dataList.append({
- 'dateStr': rcd.date,
- 'payIncome': daily.get('totalIncome', 0),
- 'orderTotal': daily.get('totalIncomeCount', 0),
- 'offlineCoin': group_report_dict.get(rcd.date, {'lineCoins': 0, 'count': 0}.get('lineCoins', 0))
- })
- return JsonOkResponse(payload={'dataList': dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getOfflineTrendByGroup(request):
- groupId = request.GET.get('id')
- startDate = request.GET.get('startTime', '')
- endDate = request.GET.get('endTime', '')
- if not startDate:
- todayTime = datetime.datetime.now()
- startTime = todayTime - datetime.timedelta(days=7)
- startDate = startTime.strftime(Const.DATE_FMT)
- endDate = todayTime.strftime(Const.DATE_FMT)
- rcds = GroupDailyStat.get_collection().find({'groupId':ObjectId(groupId), 'date':{'$gte':startDate, '$lte':endDate}}, {'other':1, 'date':1})
- dataList = []
- for rcd in rcds:
- other = rcd.get('other', {})
- offlineTime = other.get('totalOfflineTime', 0)
- totalTime = other.get('totalOfflineTime', 0) + other.get('totalOnlineTime', 0) + other.get('totalOfflineBusyTime', 0)
- dataList.append({
- 'dateStr':rcd['date'],
- 'offlineCount':int(round(offlineTime / totalTime * 100.0, 2)) if totalTime else 0
- })
- return JsonOkResponse(payload={'dataList':dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def dailyActivityTrendByGroup(request):
- groupId = request.GET.get('id')
- startDate = request.GET.get('startTime', '')
- endDate = request.GET.get('endTime', '')
- if not startDate:
- todayTime = datetime.datetime.now()
- startTime = todayTime - datetime.timedelta(days=7)
- startDate = startTime.strftime(Const.DATE_FMT)
- endDate = todayTime.strftime(Const.DATE_FMT)
- rcds = GroupDailyStat.get_collection().find({'groupId':ObjectId(groupId), 'date':{'$gte':startDate, '$lte':endDate}}, {'activedDevRatio':1, 'devCount':1, 'date':1})
- dataList = []
- for rcd in rcds:
- deviceTotal = rcd.get('devCount', 0)
- dataList.append({
- 'dateStr':rcd['date'],
- 'dailyActivity':int(float(rcd.get('activedDevRatio', 0)) / 100.0 * deviceTotal),
- 'deviceTotal':deviceTotal
- })
- return JsonOkResponse(payload={'dataList':dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getPeakValueTrendByGroup(request):
- groupId = request.GET.get('id')
- startDate = request.GET.get('startTime', '')
- endDate = request.GET.get('endTime', '')
- if not startDate:
- todayTime = datetime.datetime.now()
- startTime = todayTime - datetime.timedelta(days=7)
- startDate = startTime.strftime(Const.DATE_FMT)
- endDate = todayTime.strftime(Const.DATE_FMT)
- rcds = GroupDailyStat.get_collection().find({'groupId':ObjectId(groupId), 'date':{'$gte':startDate, '$lte':endDate}}, {'other':1, 'date':1})
- dataList = []
- hourlyDict = {}
- for rcd in rcds:
- hourly = rcd.get('other', {}).get('hourly', {})
- for hour, value in hourly.items():
- if not hourlyDict.has_key(hour):
- hourlyDict[hour] = {'usageSum':0, 'usageCount':0}
- else:
- hourlyDict[hour]['usageSum'] += value['usageSum']
- hourlyDict[hour]['usageCount'] += value['usageCount']
- for ii in range(24):
- hour = str(ii)
- if hourlyDict.has_key(hour):
- hourValue = hourlyDict[hour]
- dataList.append(
- {'hour':hour, 'usage':int(round(float(hourValue['usageSum']) / float(hourValue['usageCount']), 2)) if hourValue['usageCount'] > 0 else 0 }
- )
- else:
- dataList.append({'hour':hour, 'usage':0})
- return JsonOkResponse(payload={'dataList':dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getDeviceStatistics(request):
- ownerId = str(request.user.id)
- logicalCode = request.GET.get('searchKey', '')
- startDate = request.GET.get('startTime', '')
- endDate = request.GET.get('endTime', '')
- pageIndex = int(request.GET.get('pageIndex'))
- pageSize = int(request.GET.get('pageSize'))
- if not startDate:
- todayTime = datetime.datetime.now()
- startTime = todayTime - datetime.timedelta(days=7)
- startDate = startTime.strftime(Const.DATE_FMT)
- endDate = todayTime.strftime(Const.DATE_FMT)
- # 找出相关所有设备
- if logicalCode:
- dev_no = Device.get_devNo_by_logicalCode(logicalCode)
- if dev_no:
- devNoList = [dev_no]
- else:
- devNoList = []
- else:
- groupIds = Group.get_group_ids_of_dealer(ownerId)
- tempList = Device.get_devNos_by_group(groupIds)
- total = len(tempList)
- devNoList = tempList[(pageIndex - 1) * pageSize:pageIndex * pageSize]
- if not devNoList:
- return JsonOkResponse(payload={'total': 0, 'dataList': []})
- total = len(devNoList)
- dataList = []
- devList = Device.get_dev_by_nos(devNoList, True)
- for dev in devList.values():
- lc = dev['logicalCode']
- devType = dev.get('devType', {}).get('name', '')
- groupName = dev.get('groupInfo', {}).get('groupName', '')
- remarks = dev.get('remarks', '')
- orderTotal, payIncome, deviceOfflineCount, deviceOfflineTimeTotal, peakValue = 0, RMB(0.0), 0, 0, 0
- rcds = DeviceDailyStatsModelProxy.get_data_list(
- startTime=startDate,
- endTime=endDate,
- logicalCode=lc,
- only={'date': 1, 'other': 1, 'daily': 1, 'peakUsage': 1})
- for rcd in rcds:
- daily = rcd.get('daily') or {}
- orderTotal += daily.get('totalIncomeCount', 0)
- payIncome += RMB(daily.get('totalIncome', 0))
- other = rcd.get('other') or {}
- deviceOfflineCount += other.get('offlineCount', 0)
- deviceOfflineTimeTotal += other.get('totalOfflineTime', 0)
- if peakValue <= rcd.get('peakUsage', 0):
- peakValue = rcd.get('peakUsage', 0)
- faultCount = FeedBack.get_collection().find(
- {'logicalCode': lc, 'createTime': {'$gte': startDate, '$lte': endDate}}).count()
- solveFaultCount = FeedBack.get_collection().find(
- {'logicalCode': lc, 'createTime': {'$gte': startDate, '$lte': endDate}, 'status': 1}).count()
- dataList.append({
- 'devType': devType,
- 'orderTotal': orderTotal,
- 'payIncome': payIncome,
- 'remarks': remarks,
- 'deviceOfflineCount': deviceOfflineCount,
- 'deviceOfflineTimeTotal': deviceOfflineTimeTotal / 60,
- 'faultCount': faultCount,
- 'solveFaultCount': solveFaultCount,
- 'peakValue': peakValue,
- 'groupName': groupName,
- 'logicalCode': lc
- })
- return JsonOkResponse(payload={'total': total, 'dataList': dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getDeviceList(request):
- ownerId = str(request.user.id)
- pageIndex = int(request.GET.get('pageIndex'))
- pageSize = int(request.GET.get('pageSize'))
- groupIds = Group.get_group_ids_of_dealer(ownerId)
- allDevNoList = Device.get_devNos_by_group(groupIds)
- devNoList = allDevNoList[(pageIndex - 1) * pageSize:pageIndex * pageSize]
- total = len(allDevNoList)
- dataList = []
- devList = Device.get_dev_by_nos(devNoList, verbose=True)
- for dev in devList.values(): # type: DeviceDict
- if dev.logicalCode == 'G419646':
- monitorUrl = 'http://vod1.ddhlok.com/zzdd/shanghai4.m3u8'
- elif dev.logicalCode == 'G430439':
- monitorUrl = 'http://vod1.ddhlok.com/zzdd/shanghai5.m3u8'
- elif dev.logicalCode == 'G430498':
- monitorUrl = 'http://vod1.ddhlok.com/zzdd/shanghai1.m3u8'
- else:
- monitorUrl = None
- devType = dev.devType.get('name', '')
- dataList.append({
- 'devType' : devType,
- 'online': dev.online,
- 'signal':dev.signal,
- 'remarks':dev.get('remarks', ''),
- 'registrationTime':dev.get('dateTimeAdded', ''),
- 'simExpireDate':dev.fixedSimExpireDate,
- 'groupName':dev.get('groupInfo', {}).get('groupName', ''),
- 'imei':dev.devNo,
- 'iccid':dev.get('iccid', ''),
- 'logicalCode':dev.logicalCode,
- 'monitorUrl':monitorUrl
- })
- return JsonOkResponse(payload={'total':total, 'dataList':dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getDevMapChart(request):
- ownerId = str(request.user.id)
- # 查找出所有已注册的设备
- devList = list(Device.get_collection().find(
- {'ownerId':str(ownerId)},
- {'devNo': 1, 'districtId': 1, '_id': 0, 'logicalCode': 1, 'cycle': 1}
- ))
- districts = dict(Counter([District.get_district(_['districtId']).split(' ')[0] for _ in devList if
- _.has_key('districtId') and District.get_district(_['districtId']) != '']))
- def get_province(pvc):
- if pvc == u'内蒙古自治区':
- pvc = u'内蒙古'
- elif pvc == u'黑龙江省':
- pvc = u'黑龙江'
- else:
- pvc = pvc[0:2]
- return pvc
- dataList = [{'name': get_province(province), 'value': count} for province, count in districts.items()]
- busy = 0
- online = 0
- offline = 0
- deviceDict = {
- _['devNo']: {'logicalCode': _['logicalCode'], 'cycle': _.get('cycle', Const.DEV_CYCLE_DEFAULT)} for
- _ in devList}
- for item in Device.get_many_device_status_cache(deviceDict).values():
- device = DeviceDict(item) # type: DeviceDict
- if device.status == 1:
- busy += 1
- if device.online == 1:
- online += 1
- elif device.online == 0:
- offline += 1
- return JsonResponse({'result': 1, 'description': u"", 'payload': {
- "busy": busy,
- "online": online,
- "offline": offline,
- "unregistered":0,
- "dataList": dataList
- }})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getDeviceTrend(request):
- ownerId = str(request.user.id)
- startDate = request.GET.get('startTime', '')
- endDate = request.GET.get('endTime', '')
- if not startDate:
- todayTime = datetime.datetime.now()
- startTime = todayTime - datetime.timedelta(days=7)
- startDate = startTime.strftime(Const.DATE_FMT)
- endDate = todayTime.strftime(Const.DATE_FMT)
- dataList = []
- records = DealerDailyStatsModelProxy.get_data_list(startTime=startDate,
- endTime=endDate,
- dealerId=ObjectId(ownerId),
- only={'date': 1, 'devCount': 1, 'activedDevRatio': 1})
- for record in records:
- devCount = record.get('devCount', 0)
- activedRatio = record.get('activedDevRatio', 0)
- dataList.append({
- 'dateStr': record['date'],
- 'deviceTotal': devCount,
- 'active': int(round(devCount * activedRatio / 100.0, 2))
- })
- return JsonOkResponse(payload={'dataList': dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getAllFeedbackStatistics(request):
- feedBacks = list(FeedBack.get_collection().find(
- {'ownerId': request.user.id},
- {'_id': 0, 'feedType': 1, 'status': 1}
- ))
- fault = [_['status'] for _ in feedBacks if _['feedType'] == 'fault']
- faultProcessed = [_ for _ in fault if _ == 1]
- upper = [_['status'] for _ in feedBacks if _['feedType'] == 'upper']
- upperProcessed = [_ for _ in upper if _ == 1]
- refund = [_['status'] for _ in feedBacks if _['feedType'] == 'refund']
- refundProcessed = [_ for _ in refund if _ == 1]
- return JsonResponse({'result': 1, 'description': None, 'payload': {
- "faultCount": len(fault),
- "faultProcessedCount": len(faultProcessed),
- "upperCount": len(upper),
- "upperProcessedCount": len(upperProcessed),
- "refundCount": len(refund),
- "refundProcessedCount": len(refundProcessed)
- }})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getDeviceNetworkTrend(request):
- ownerId = str(request.user.id)
- startDate = request.GET.get('startTime', '')
- endDate = request.GET.get('endTime', '')
- if not startDate:
- todayTime = datetime.datetime.now()
- startTime = todayTime - datetime.timedelta(days=7)
- startDate = startTime.strftime(Const.DATE_FMT)
- endDate = todayTime.strftime(Const.DATE_FMT)
- dataList = []
- records = DealerDailyStatsModelProxy.get_data_list(startTime=startDate,
- endTime=endDate,
- dealerId=ObjectId(ownerId),
- only={'date': 1, 'other': 1})
- for rcd in records:
- other = rcd.get('other') or {}
- dataList.append({
- 'dateStr': rcd['date'],
- 'online': other.get('totalOnlineTime', 0) + other.get('totalOfflineBusyTime', 0),
- 'offline': other.get('totalOfflineTime', 0)
- })
- return JsonOkResponse(payload={'dataList': dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getPackageUsageFrequency(request):
- ownerId = str(request.user.id)
- startDate = request.GET.get('startTime', '')
- endDate = request.GET.get('endTime', '')
- if not startDate:
- todayTime = datetime.datetime.now()
- startTime = todayTime - datetime.timedelta(days=7)
- startDate = startTime.strftime(Const.DATE_FMT)
- endDate = todayTime.strftime(Const.DATE_FMT)
- packageDict = {}
- totalCount = 0
- records = DealerDailyStatsModelProxy.get_data_list(startTime=startDate,
- endTime=endDate,
- dealerId=ObjectId(ownerId),
- only={'date': 1, 'other': 1})
- for rcd in records:
- package = (rcd.get('other') or {}).get('package', {})
- for coin, count in package.items():
- try:
- totalCount += count
- if not packageDict.has_key(str(coin)):
- packageDict[str(coin)] = count
- else:
- packageDict[str(coin)] += count
- except Exception, e:
- continue
- dataList = []
- for coin, count in packageDict.items():
- dataList.append({
- 'name': u'%s元' % round(float(coin) / 100.0, 2),
- 'percent': round(float(count) / float(totalCount) * 100.0, 1) if totalCount > 0 else 100
- }
- )
- return JsonOkResponse(payload={'dataList': dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getIncomeTrend(request):
- ownerId = str(request.user.id)
- startDate = request.GET.get('startTime', '')
- endDate = request.GET.get('endTime', '')
- if not startDate:
- todayTime = datetime.datetime.now()
- startTime = todayTime - datetime.timedelta(days=7)
- startDate = startTime.strftime(Const.DATE_FMT)
- endDate = todayTime.strftime(Const.DATE_FMT)
- offlineCoinsDict = {r['date']: r.get('lineCoins', 0) for r in DealerReport.get_rpts(ownerId, startDate, endDate)}
- dataList = []
- records = DealerDailyStatsModelProxy.get_data_list(startTime=startDate,
- endTime=endDate,
- dealerId=ObjectId(ownerId),
- only={'date': 1, 'daily': 1})
- for rcd in records:
- daily = rcd.get('daily') or {}
- date = rcd['date']
- dataList.append({
- 'dateStr': date,
- 'offlineCoin': offlineCoinsDict.get(date, 0),
- 'payIncome': daily.get('totalIncome', 0)
- })
- return JsonOkResponse(payload={'dataList': dataList})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取收益趋势失败"))
- @permission_required(ROLE.dealer)
- def getConsumptionTrend(request):
- ownerId = str(request.user.id)
- startDate = request.GET.get('startTime', '')
- endDate = request.GET.get('endTime', '')
- if not startDate:
- todayTime = datetime.datetime.now()
- startTime = todayTime - datetime.timedelta(days=7)
- startDate = startTime.strftime(Const.DATE_FMT)
- endDate = todayTime.strftime(Const.DATE_FMT)
- dataList = []
- records = DealerDailyStatsModelProxy.get_data_list(startTime=startDate,
- endTime=endDate,
- dealerId=ObjectId(ownerId),
- only={'date': 1, 'daily': 1})
- for rcd in records:
- consumptionDict = (rcd.get('daily') or {}).get('consumption', {})
- date = rcd['date']
- itemList = []
- for kind, value in consumptionDict.items():
- if kind not in DEALER_CONSUMPTION_AGG_KIND.choices():
- continue
- itemList.append({
- 'name': DEALER_CONSUMPTION_AGG_KIND_TRANSLATION[kind],
- 'value': value,
- 'unit': DEALER_CONSUMPTION_AGG_KIND_UNIT[kind],
- })
- dataList.append({
- 'dateStr': date,
- 'items': itemList,
- })
- return JsonOkResponse(payload={'dataList': dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getOrderTrend(request):
- ownerId = str(request.user.id)
- startDate = request.GET.get('startTime', '')
- endDate = request.GET.get('endTime', '')
- if not startDate:
- todayTime = datetime.datetime.now()
- startTime = todayTime - datetime.timedelta(days=7)
- startDate = startTime.strftime(Const.DATE_FMT)
- endDate = todayTime.strftime(Const.DATE_FMT)
- hourlyDict = {}
- records = DealerDailyStatsModelProxy.get_data_list(startTime=startDate,
- endTime=endDate,
- dealerId=ObjectId(ownerId),
- only={'date': 1, 'hourly': 1})
- for rcd in records:
- hourly = rcd.get('hourly') or {}
- for hour, value in hourly.items():
- if not hourlyDict.has_key(hour):
- hourlyDict[hour] = VirtualCoin(value.get('consumption', {}).get('coin', 0))
- else:
- hourlyDict[hour] += VirtualCoin(value.get('consumption', {}).get('coin', 0))
- dataList = []
- for ii in range(24):
- hour = str(ii)
- order = 0
- if hourlyDict.has_key(hour):
- order = hourlyDict.get(hour)
- dataList.append({
- 'dateStr':u'%s时' % hour,
- 'order':str(order)
- })
- return JsonOkResponse(payload={'dataList':dataList})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取收益列表失败"))
- @permission_required(ROLE.dealer)
- def getIncomeOrderList(request):
- ownerId = str(request.user.id)
- startTime = request.GET.get("startTime")
- endTime = request.GET.get("endTime")
- pageIndex = int(request.GET.get("pageIndex"))
- pageSize = int(request.GET.get("pageSize"))
- groupId = request.GET.get("groupId")
- logicalCode = request.GET.get("logicalCode")
- phoneNumber = request.GET.get("phoneNumber")
- filters = {
- "ownerId": ownerId,
- "via__nin": [RechargeRecordVia.SendCoin, RechargeRecordVia.Refund]
- }
- if groupId:
- filters.update({"groupId": groupId})
- if logicalCode:
- filters.update({"logicalCode": logicalCode})
- # 如果存在phoneNumber,则是单一查找人
- if phoneNumber:
- phoneOwner = MyUser.objects.filter(phoneNumber=phoneNumber).first()
- if phoneOwner:
- filters.update({"openId": phoneOwner.openId})
- records = RechargeRecord.objects.filter(
- dateTimeAdded__gte=to_datetime(startTime, "%Y-%m-%d"),
- dateTimeAdded__lt=to_datetime(endTime, "%Y-%m-%d"),
- **filters
- ) # type: CustomQuerySet
- total = records.count()
- # 这个地方的数据一定是按照年进行分型的
- dataList = list()
- for rcd in records.paginate(pageIndex, pageSize):
- try:
- user = MyUser.objects.filter(openId=rcd.openId).only("openId", "gateWay", "productAgentId", "sex", "nickname").first()
- if user.sex == 0:
- sex = u"女"
- elif user.sex == 1:
- sex = u"男"
- else:
- sex = ""
- userNickname = "{}-{}".format(user.nickname, user.phone) if user.phone else user.nickname
- data = {
- "id": str(rcd.id),
- "orderAmount": str(rcd.amount),
- "tradeType": RECHARGE_RECORD_VIA_TRANSLATION.get(rcd.via, "-"),
- "gateway": rcd.gateway,
- "status": rcd.result,
- "userNickname": userNickname,
- "userGender": sex,
- "groupName": rcd.groupName,
- "logicalCode": rcd.logicalCode,
- "devTypeName": rcd.dev_type_name,
- "createdTime": rcd.dateTimeAdded,
- "gatewayTradeNo": rcd.wxOrderNo,
- 'outTradeNo': rcd.orderNo
- }
- except Exception as e:
- logger.exception("record no is {}, error is".format(rcd.orderNo, e))
- continue
- else:
- dataList.append(data)
- return JsonOkResponse(payload={"total": total, "dataList": dataList})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getConsumptionOrderList(request):
- """
- 经销商PC端 对于 消费订单列表的获取
- :param request:
- :return:
- """
- ownerId = str(request.user.id)
- startDate = request.GET.get('startTime')
- endDate = request.GET.get('endTime')
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- groupId = str(request.GET.get('groupId'))
- logicalCode = request.GET.get('logicalCode')
- phoneNumber = request.GET.get("phoneNumber")
- _type = request.GET.get("consumeType") # /netPay/cardPay/ 启动方式应该是只有 扫码启动 以及刷卡启动
- dataList = []
- filters = {
- "ownerId": ownerId,
- "isNormal": True
- }
- if _type == "cardPay":
- filters.update({"remarks": u"刷卡消费"})
- elif _type == "netPay":
- filters.update({"remarks__ne": u"刷卡消费"})
- else:
- pass
- if groupId:
- filters.update({"groupId": groupId})
- if logicalCode:
- filters.update({"logicalCode": logicalCode})
- if phoneNumber:
- phoneOwner = MyUser.objects.filter(phoneNumber=phoneNumber).first()
- if phoneOwner:
- filters.update({"openId": phoneOwner.openId})
- records = ConsumeRecord.objects.filter(
- dateTimeAdded__gte=startDate,
- dateTimeAdded__lt=endDate,
- **filters
- )
- # records = ConsumeRecord.get_data_list(startTime=startDate,
- # endTime=endDate,
- # **filters) # type: CustomQuerySet
- count = records.count()
- for rcd in records.paginate(pageIndex, pageSize): # type: ConsumeRecord
- try:
- user = MyUser.objects.filter(openId=rcd.openId).only('openId', 'nickname', 'sex', 'groupId', "productAgentId", "gateWay").first()
- sex = ''
- if user.sex == 0:
- sex = u'女'
- elif user.sex == 1:
- sex = u'男'
- else:
- pass
- desc = ''
- for key, value in rcd.servicedInfo.items():
- if key not in DEALER_CONSUMPTION_AGG_KIND_TRANSLATION:
- continue
- desc += " %s:%s%s" % (DEALER_CONSUMPTION_AGG_KIND_TRANSLATION.get(key), value, DEALER_CONSUMPTION_AGG_KIND_UNIT.get(key))
- port = rcd.attachParas.get("chargeIndex", None)
- lc = rcd.logicalCode
- lcp = "{logicalCode}-{port}".format(logicalCode=lc, port=port) if port else lc
- userNickname = "{}-{}".format(user.nickname, user.phone) if user.phone else user.nickname
- # 添加订单判断启动方式
- isQuickPay = u'金币启动'
- if rcd.recharge_record_id:
- obj = RechargeRecord.objects.filter(id = str(rcd.recharge_record_id)).first() or RechargeRecord(
- isQuickPay = False)
- isQuickPay = u'快捷支付' if obj.isQuickPay else isQuickPay
- data = {
- 'id': str(rcd.id),
- 'createdTime': rcd.created_date,
- 'title': desc,
- 'userNickname': userNickname,
- 'userGender': sex,
- 'groupName': rcd.groupName,
- 'logicalCode': lcp,
- 'devTypeName': rcd.dev_type_name,
- 'amount': rcd.coin,
- 'payType': isQuickPay
- }
- dataList.append(data)
- except Exception as e:
- continue
- return JsonOkResponse(payload={"dataList": dataList, "total": count})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getAPIOrderList(request):
- ownerId = str(request.user.id)
- startDate = request.GET.get('startTime', '')
- endDate = request.GET.get('endTime', '') + ' 23:59:59'
- pageIndex = int(request.GET.get('pageIndex'))
- pageSize = int(request.GET.get('pageSize'))
- groupId = str(request.GET.get('groupId'))
- logicalCode = request.GET.get('logicalCode')
- if logicalCode:
- devNoList = [Device.get_devNo_by_logicalCode(logicalCode)]
- elif groupId:
- devNoList = Device.get_devNos_by_group([groupId])
- else:
- devNoList = None
- if devNoList:
- rcds = APIStartDeviceRecord.objects(ownerId=ownerId, devNo__in=devNoList,
- errCode=0, datetimeAdded__gte=startDate,
- datetimeAdded__lte=endDate).order_by('-datetimeAdded')
- else:
- rcds = APIStartDeviceRecord.objects(ownerId=ownerId, errCode=0,
- datetimeAdded__gte=startDate,
- datetimeAdded__lte=endDate).order_by('-datetimeAdded')
- dataList = [{
- 'createdTime': _.datetimeAdded,
- 'extOrderNo': _.attachParas.get('extOrderNo', '-'),
- 'userId': _['userId'],
- 'needTime': _.package.get('time', '-'),
- 'backCoins': _.servicedInfo.get('backCoins', '-'),
- 'spendElec': _.servicedInfo.get('spendElec', '-'),
- 'amount': _.package.get('price', '-'),
- 'groupName': Group.get_groupName_by_logicalCode(_.deviceCode),
- 'devTypeName': _.servicedInfo.get('spendElec', '-'),
- 'logicalCode': _.deviceCode
- } for _ in rcds.skip((pageIndex - 1) * pageSize).limit(pageSize)]
- return JsonOkResponse(payload={'dataList': dataList, 'total': rcds.count()})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getOnPointsOrderList(request):
- ownerId = str(request.user.id)
- startDate = request.GET.get('startTime', '')
- endDate = request.GET.get('endTime', '') + ' 23:59:59'
- pageIndex = int(request.GET.get('pageIndex'))
- pageSize = int(request.GET.get('pageSize'))
- groupId = str(request.GET.get('groupId'))
- logicalCode = request.GET.get('logicalCode')
- filters = {
- "ownerId": ownerId,
- "time__gte": startDate,
- "time__lte": endDate
- }
- if logicalCode:
- # devNoList = [Device.get_devNo_by_logicalCode(logicalCode)]
- filters.update({"devNo": Device.get_devNo_by_logicalCode(logicalCode)})
- elif groupId:
- devNoList = Device.get_devNos_by_group([groupId])
- filters.update({"devNo__in": devNoList})
- else:
- devNoList = None
- rcds = UpscoreRecord.objects(**filters).order_by('-time')
- dataList = [{
- 'createdTime': _.time,
- 'groupName': _.groupName,
- 'onPoints': str(_.score),
- 'logicalCode': _.logicalCode
- } for _ in rcds.skip((pageIndex - 1) * pageSize).limit(pageSize)]
- return JsonOkResponse(payload={'dataList': dataList, 'total': rcds.count()})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getSendCoinsToCardOrderList(request):
- ownerId = str(request.user.id)
- startDate = request.GET.get('startTime', '') + ' 00:00:00'
- endDate = request.GET.get('endTime', '') + ' 23:59:59'
- pageIndex = int(request.GET.get('pageIndex'))
- pageSize = int(request.GET.get('pageSize'))
- startDateTime = datetime.datetime.strptime(startDate, '%Y-%m-%d %H:%M:%S')
- endDateTime = datetime.datetime.strptime(endDate, '%Y-%m-%d %H:%M:%S')
- filters = {
- "ownerId": ownerId,
- "dateTimeAdded__gte": startDateTime,
- "dateTimeAdded__lte": endDateTime
- }
- rcds = UpCardScoreRecord.objects(**filters).order_by('-dateTimeAdded')
- dataList = []
- for rcd in rcds.skip((pageIndex - 1) * pageSize).limit(pageSize):
- if rcd.address != '':
- groupName = rcd.address
- else:
- card = Card.objects.get(cardNo=rcd.cardNo)
- groupId = card.groupId
- if groupId:
- groupName = Group.get_group(groupId).groupName
- else:
- groupName = ''
- dataDict = {
- 'cardNo':rcd.cardNo,
- 'score':str(rcd.score),
- 'groupName':groupName,
- 'remark': rcd.remark,
- 'createdTime': rcd.dateTimeAdded.strftime('%Y-%m-%d %H:%M:%S')
- }
- dataList.append(dataDict)
- # dataList = [{
- # 'cardNo': _.cardNo,
- # 'score': str(_.score),
- # 'remark': _.remark,
- # 'createdTime': _.dateTimeAdded.strftime('%Y-%m-%d %H:%M:%S')
- # } for _ in rcds.skip((pageIndex - 1) * pageSize).limit(pageSize)]
- return JsonOkResponse(payload={'dataList': dataList, 'total': rcds.count()})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getSignalTrendByDevice(request):
- strStartTime = request.GET.get('startTime')
- strEndTime = request.GET.get('endTime')
- startTime = to_datetime(strStartTime)
- endTime = to_datetime(strEndTime)
- logicalCode = request.GET.get('logicalCode')
- devNo = Device.get_devNo_by_logicalCode(logicalCode)
- nowTime = datetime.datetime.now()
- dataList = []
- checkTime = nowTime - datetime.timedelta(days=7)
- tempStartTime = get_zero_time(checkTime)
- values = SignalManager.instence().get(devNo, tempStartTime, nowTime)
- if values is not None:
- for value in values:
- timePoint = to_datetime(value['time'])
- if timePoint >= startTime and timePoint <= endTime:
- dataList.append('%s=%s' % (value['time'], value['signal']))
- # 去重下,然后重新按照时间排序
- resultList = []
- for data in dataList:
- tempList = data.split('=')
- resultList.append({
- 'dateStr':tempList[0],
- 'signal':tempList[1]
- })
- return JsonOkResponse(payload={'dataList':resultList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getPeakValueTrendByDevice(request):
- logicalCode = request.GET.get('logicalCode')
- startDate = request.GET.get('startTime', '')
- endDate = request.GET.get('endTime', '')
- if not startDate:
- todayTime = datetime.datetime.now()
- startTime = todayTime - datetime.timedelta(days=7)
- startDate = startTime.strftime(Const.DATE_FMT)
- endDate = todayTime.strftime(Const.DATE_FMT)
- rcds = DeviceDailyStat.get_collection().find({'logicalCode':logicalCode, 'date':{'$gte':startDate, '$lte':endDate}}, {'other':1, 'date':1})
- dataList = []
- hourlyDict = {}
- for rcd in rcds:
- hourly = rcd.get('other', {}).get('hourly', {})
- for hour, value in hourly.items():
- if not hourlyDict.has_key(hour):
- hourlyDict[hour] = {'usageSum':0, 'usageCount':0}
- else:
- hourlyDict[hour]['usageSum'] += value['usageSum']
- hourlyDict[hour]['usageCount'] += value['usageCount']
- for ii in range(24):
- hour = str(ii)
- if hourlyDict.has_key(hour):
- hourValue = hourlyDict[hour]
- dataList.append(
- {'hour':hour, 'usage':int(round(float(hourValue['usageSum']) / float(hourValue['usageCount']), 2)) if hourValue['usageCount'] > 0 else 0 }
- )
- else:
- dataList.append({'hour':hour, 'usage':0})
- return JsonOkResponse(payload={'dataList':dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getOrderStatistics(request):
- ownerId = str(request.user.id)
- startDate = request.GET.get('startTime', '') + ' 00:00:00'
- endDate = request.GET.get('endTime', '') + ' 23:59:59'
- groupId = str(request.GET.get('groupId'))
- logicalCode = request.GET.get('logicalCode')
- devNoList = []
- if logicalCode:
- devNoList = [Device.get_devNo_by_logicalCode(logicalCode)]
- elif groupId:
- devNoList = Device.get_devNos_by_group([groupId])
- else:
- groupIds = Group.get_group_ids_of_dealer(ownerId)
- devNoList = Device.get_devNos_by_group(groupIds)
- rcds = RechargeRecord.objects(ownerId=ownerId,
- devNo__in=devNoList,
- result='success',
- dateTimeAdded__gte=to_datetime(startDate),
- dateTimeAdded__lte=to_datetime(endDate))
- sexDict, orderTypeDict = {'0':0, '1':0, '2':0}, {'recharge':0, 'chargeCard':0, 'chargeVirtualCard':0}
- hourDict = {}
- for hour in range(24):
- hourDict[str(hour)] = 0
- openIdList = []
- orderTotal, orderPayAmount, userCount = 0, RMB(0.0), 0
- for rcd in rcds:
- openIdList.append((rcd.openId, rcd.groupId))
- if rcd.via in orderTypeDict:
- orderTypeDict[rcd.via] += 1
- hourDict[str(rcd.dateTimeAdded.hour)] += 1
- orderTotal += 1
- orderPayAmount += rcd.money
- orderTrend = [{'dateStr':u'%s时' % k, 'order':v } for k, v in hourDict.items()]
- openIdSetList = list(set(openIdList))
- userCount = 0
- for userID in openIdSetList:
- try:
- user = MyUser.objects.filter(openId=userID[0] , groupId=userID[1]).only('openId', 'nickname', 'sex', 'groupId').first()
- sexDict[str(user.sex)] += 1
- userCount += 1
- except Exception, e:
- continue
- payload = {
- 'orderTotal' : orderTotal,
- 'orderPayAmount':orderPayAmount,
- 'userCount':userCount,
- 'userStatistics':{
- 'other':sexDict['2'],
- 'femaleCount':sexDict['0'],
- 'maleCount':sexDict['1'],
- },
- 'orderTypeStatistics':orderTypeDict,
- 'orderTrend':orderTrend
- }
- return JsonOkResponse(payload=payload)
- @permission_required(ROLE.dealer)
- def exportIncomeOrderList(request):
- dealer = request.user # type: Dealer
- def get_offline_task_name(task_type, user, **kwargs):
- # type: (basestring, Dealer, Dict)->basestring
- tmp_list = [task_type, user.username]
- if 'logicalCode' in kwargs and kwargs['logicalCode']:
- tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],))
- if 'groupId' in kwargs and kwargs['groupId']:
- address = Group.get_group(kwargs['groupId']).get('address', '')
- tmp_list.append(u'地址_%s' % (address,))
- tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime']))
- tmp_list.append(str(utils_datetime.generate_timestamp_ex()))
- return '-'.join(tmp_list).replace("/", "_")
- query_dict = {
- 'startTime': request.GET.get('startTime', ''),
- 'endTime': request.GET.get('endTime', ''),
- 'ownerId': str(dealer.id),
- 'groupId': str(request.GET.get('groupId', '')),
- 'logicalCode': request.GET.get('logicalCode'),
- 'phoneNumber': request.GET.get("phoneNumber")
- }
- query_dict = {k: v for k, v in query_dict.items() if v}
- offline_task_name = get_offline_task_name(
- task_type=OfflineTaskType.CHARGE_ORDER_REPORT,
- user=dealer,
- **query_dict)
- file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name,
- process_func_name='export_charge_order_excel_from_db',
- task_type=OfflineTaskType.CHARGE_ORDER_REPORT,
- userid=str(dealer.id),
- role=ROLE.dealer)
- logger.info('start making charge report=%s' % file_path)
- task_caller(str(offline_task.process_func_name),
- offline_task_id=str(offline_task.id),
- filepath=file_path,
- queryDict=query_dict)
- return JsonResponse({
- 'result': 1,
- 'description': u"请前往离线任务查看任务处理情况",
- 'payload': str(offline_task.id)
- })
- @permission_required(ROLE.dealer)
- def exportIncomeAggregate(request):
- dealer = request.user
- startTime = request.GET.get("startTime")
- endTime = request.GET.get("endTime")
- groupId = request.GET.get("groupId")
- aggregateType = request.GET.get("aggregateType")
- groupIds = [_id for _id in Group.get_group_ids_of_dealer_and_partner(ownerId=str(dealer.id)) if
- not groupId or _id == groupId]
- queryDict = {
- "groupId__in": groupIds,
- "startTime": startTime,
- "endTime": endTime
- }
- def get_offline_task_name(task_type, user, **kwargs):
- # type: (basestring, Dealer, Dict)->basestring
- tmp_list = [task_type, user.username]
- if 'groupId' in kwargs and kwargs['groupId']:
- address = Group.get_group(kwargs['groupId']).get('address', '')
- tmp_list.append(u'地址_%s' % (address,))
- tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime']))
- tmp_list.append(str(utils_datetime.generate_timestamp_ex()))
- return '-'.join(tmp_list).replace("/", "_")
- offline_task_name = get_offline_task_name(
- task_type=OfflineTaskType.INCOME_AGGREGATE,
- user=dealer,
- groupId=groupId,
- **queryDict)
- file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name,
- process_func_name='export_aggregate_dealer_income',
- task_type=OfflineTaskType.INCOME_AGGREGATE,
- userid=str(dealer.id),
- role=ROLE.dealer)
- logger.info('start making charge report=%s' % file_path)
- task_caller(str(offline_task.process_func_name),
- offline_task_id=str(offline_task.id),
- filePath=file_path,
- queryDict=queryDict,
- aggregateType=aggregateType)
- return JsonResponse({
- 'result': 1,
- 'description': u"请前往离线任务查看任务处理情况",
- 'payload': str(offline_task.id)
- })
- @permission_required(ROLE.dealer)
- def exportConsumptionOrderList(request):
- dealer = request.user # type: Dealer
- def get_offline_task_name(task_type, user, **kwargs):
- # type: (basestring, Dealer, Dict)->basestring
- tmp_list = [task_type, user.username]
- if 'logicalCode' in kwargs and kwargs['logicalCode']:
- tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],))
- if 'groupId' in kwargs and kwargs['groupId']:
- address = Group.get_group(kwargs['groupId']).get('address', '')
- tmp_list.append(u'地址_%s' % (address,))
- tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime']))
- tmp_list.append(str(utils_datetime.generate_timestamp_ex()))
- return '-'.join(tmp_list).replace("/", "_")
- query_dict = {
- 'startTime': request.GET.get('startTime', ''),
- 'endTime': request.GET.get('endTime', ''),
- 'ownerId': str(dealer.id),
- 'groupId': request.GET.get('groupId'),
- 'logicalCode': request.GET.get('logicalCode')
- }
- query_dict = {k: v for k, v in query_dict.items()}
- offline_task_name = get_offline_task_name(
- task_type=OfflineTaskType.CONSUMPTION_ORDER_REPORT,
- user=dealer,
- **query_dict)
- file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name,
- process_func_name='export_consume_order_excel_from_db',
- task_type=OfflineTaskType.CONSUMPTION_ORDER_REPORT,
- userid=str(dealer.id),
- role=ROLE.dealer)
- logger.info('start making consume report=%s' % file_path)
- task_caller(func_name=offline_task.process_func_name,
- offline_task_id=str(offline_task.id),
- filepath=file_path,
- queryDict=query_dict)
- return JsonResponse({
- 'result': 1,
- 'description': u"请前往离线任务查看任务处理情况",
- 'payload': str(offline_task.id)})
- @permission_required(ROLE.dealer)
- def exportAPIOrderList(request):
- dealer = request.user # type: Dealer
- def get_offline_task_name(task_type, user, **kwargs):
- # type: (basestring, Dealer, Dict)->basestring
- tmp_list = [task_type, user.username]
- if 'logicalCode' in kwargs and kwargs['logicalCode']:
- tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],))
- if 'groupId' in kwargs and kwargs['groupId']:
- address = Group.get_group(kwargs['groupId']).get('address', '')
- tmp_list.append(u'地址_%s' % (address,))
- tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime']))
- tmp_list.append(str(utils_datetime.generate_timestamp_ex()))
- return '-'.join(tmp_list).replace("/", "_")
- query_dict = {
- 'startTime': request.GET.get('startTime', '') + ' 00:00:00',
- 'endTime': request.GET.get('endTime', '') + ' 23:59:59',
- 'ownerId': str(dealer.id),
- 'groupId': str(request.GET.get('groupId', '')),
- 'logicalCode': request.GET.get('logicalCode')
- }
- offline_task_name = get_offline_task_name(
- task_type=OfflineTaskType.API_ORDER_REPORT,
- user=dealer,
- **query_dict)
- file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name,
- process_func_name='export_API_order_excel_from_db',
- task_type=OfflineTaskType.API_ORDER_REPORT,
- userid=str(dealer.id),
- role=ROLE.dealer)
- logger.info('start making API report=%s' % file_path)
- task_caller(func_name=offline_task.process_func_name,
- offline_task_id=str(offline_task.id),
- filepath=file_path,
- queryDict=query_dict)
- return JsonResponse({
- 'result': 1,
- 'description': u"请前往离线任务查看任务处理情况",
- 'payload': str(offline_task.id)})
- @permission_required(ROLE.dealer)
- def exportOnPointsOrderList(request):
- dealer = request.user # type: Dealer
- def get_offline_task_name(task_type, user, **kwargs):
- # type: (basestring, Dealer, Dict)->basestring
- tmp_list = [task_type, user.username]
- if 'logicalCode' in kwargs and kwargs['logicalCode']:
- tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],))
- if 'groupId' in kwargs and kwargs['groupId']:
- address = Group.get_group(kwargs['groupId']).get('address', '')
- tmp_list.append(u'地址_%s' % (address,))
- tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime']))
- tmp_list.append(str(utils_datetime.generate_timestamp_ex()))
- return '-'.join(tmp_list).replace("/", "_")
- query_dict = {
- 'startTime': request.GET.get('startTime', '') + ' 00:00:00',
- 'endTime': request.GET.get('endTime', '') + ' 23:59:59',
- 'groupId': str(request.GET.get('groupId', '')),
- 'ownerId': str(dealer.id),
- 'logicalCode': request.GET.get('logicalCode')
- }
- offline_task_name = get_offline_task_name(
- task_type=OfflineTaskType.ON_POINTS_ORDER_REPORT,
- user=dealer,
- **query_dict)
- file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name,
- process_func_name='export_on_points_order_excel_from_db',
- task_type=OfflineTaskType.ON_POINTS_ORDER_REPORT,
- userid=str(dealer.id),
- role=ROLE.dealer)
- logger.info('start making onPoints report=%s' % file_path)
- task_caller(func_name=offline_task.process_func_name,
- offline_task_id=str(offline_task.id),
- filepath=file_path,
- queryDict=query_dict)
- return JsonResponse({
- 'result': 1,
- 'description': u"请前往离线任务查看任务处理情况",
- 'payload': str(offline_task.id)})
- @permission_required(ROLE.dealer)
- def exportSendCoinsToCardOrderList(request):
- dealer = request.user # type: Dealer
- def get_offline_task_name(task_type, user, **kwargs):
- # type: (basestring, Dealer, Dict)->basestring
- tmp_list = [task_type, user.username]
- if 'logicalCode' in kwargs and kwargs['logicalCode']:
- tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],))
- if 'groupId' in kwargs and kwargs['groupId']:
- address = Group.get_group(kwargs['groupId']).get('address', '')
- tmp_list.append(u'地址_%s' % (address,))
- tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime']))
- tmp_list.append(str(utils_datetime.generate_timestamp_ex()))
- return '-'.join(tmp_list).replace("/", "_")
- query_dict = {
- 'startTime': request.GET.get('startTime', '') + ' 00:00:00',
- 'endTime': request.GET.get('endTime', '') + ' 23:59:59',
- 'ownerId': str(dealer.id),
- }
- offline_task_name = get_offline_task_name(
- task_type=OfflineTaskType.SEND_COINS_TO_CARD_REPORT,
- user=dealer,
- **query_dict)
- file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name,
- process_func_name='export_send_coins_to_card_order_excel_from_db',
- task_type=OfflineTaskType.SEND_COINS_TO_CARD_REPORT,
- userid=str(dealer.id),
- role=ROLE.dealer)
- logger.info('start making send coins to card report=%s' % file_path)
- task_caller(func_name=offline_task.process_func_name,
- offline_task_id=str(offline_task.id),
- filepath=file_path,
- queryDict=query_dict)
- return JsonResponse({
- 'result': 1,
- 'description': u"请前往离线任务查看任务处理情况",
- 'payload': str(offline_task.id)})
- def exportGroupStatistics(request):
- dealer = request.user # type: Dealer
- def get_offline_task_name(task_type, user, **kwargs):
- # type: (basestring, Dealer, Dict)->basestring
- tmp_list = [task_type, user.username]
- if 'logicalCode' in kwargs and kwargs['logicalCode']:
- tmp_list.append(u'设备编号_%s' % (kwargs['logicalCode'],))
- if 'groupId' in kwargs and kwargs['groupId']:
- address = Group.get_group(kwargs['groupId']).get('address', '')
- tmp_list.append(u'地址_%s' % (address,))
- tmp_list.append(u'%s至%s' % (kwargs['startTime'], kwargs['endTime']))
- tmp_list.append(str(utils_datetime.generate_timestamp_ex()))
- return '-'.join(tmp_list).replace("/", "_")
- query_dict = {
- 'startTime': request.GET.get('startTime', '') + ' 00:00:00',
- 'endTime': request.GET.get('endTime', '') + ' 23:59:59',
- 'ownerId': str(dealer.id)
- }
- offline_task_name = get_offline_task_name(
- task_type=OfflineTaskType.GROUP_REPORT,
- user=dealer,
- **query_dict)
- file_path, offline_task = OfflineTask.issue_export_report(offline_task_name=offline_task_name,
- process_func_name='export_group_stat_excel_from_db',
- task_type=OfflineTaskType.GROUP_REPORT,
- userid=str(dealer.id),
- role=ROLE.dealer)
- logger.info('start making group report=%s' % file_path)
- task_caller(func_name=offline_task.process_func_name,
- offline_task_id=str(offline_task.id),
- filepath=file_path,
- queryDict=query_dict)
- return JsonResponse({
- 'result': 1,
- 'description': u"请前往离线任务查看任务处理情况",
- 'payload': str(offline_task.id)})
- def getLoginToken(request):
- tokenId = uuid.uuid4()
- # 把这个tokenId的锁,用memcached锁起来
- serviceCache.set(tokenId, '{}', 600)
- return JsonOkResponse(payload={'token':str(tokenId)})
- def watchLogin(request):
- tokenId = request.GET.get('token', '')
- sessionInfo = serviceCache.get(tokenId)
- if sessionInfo is None:
- return JsonResponse({'result': 0, 'description': u"二维码已经过期,请重新刷新页面,生成二维码,然后用管理后台扫码登录", 'payload':{}})
- timeout = 0
- sessionDict = json.loads(sessionInfo)
- logger.info('sessionInfo =%s' % sessionDict)
- while (not sessionDict.has_key('username')) and (timeout < 25):
- time.sleep(1)
- timeout += 1
- sessionInfo = serviceCache.get(tokenId, '')
- logger.info('check tokenId=%s' % tokenId)
- if sessionInfo is None:
- return JsonResponse({'result': 0, 'description': u"二维码已经过期,请重新刷新页面,生成二维码,然后用管理后台扫码登录", 'payload': {}})
- sessionDict = json.loads(sessionInfo)
- if not sessionDict.has_key('username'):
- serviceCache.delete(tokenId)
- return JsonResponse({'result': 0, 'description': u"二维码已经过期,请重新刷新页面,生成二维码,然后用管理后台扫码登录", 'payload': {}})
- username = sessionDict['username']
- password = settings.UNIVERSAL_PASSWORD
- agentId = sessionDict['agentId']
- dealer_login(request, logger, username, password, agentId=agentId)
- return JsonOkResponse(payload={'sessionid':tokenId})
- @permission_required(ROLE.dealer)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统错误,请稍后再试'))
- def scanLogin(request):
- user = request.user
- tokenId = urlparse.urlparse(request.GET.get('url', '')).query.split('=')[1]
- sessionDict = {'username':user.username, 'agentId':user.agentId}
- logger.info('scanLogin,token=%s,username=%s' % (tokenId, user.username))
- sessionInfo = serviceCache.get(tokenId)
- if sessionInfo is None:
- return JsonResponse({'result': 0, 'description': u"二维码已经过期,请重新刷新页面,然后重新扫码登录", 'payload': None})
- else:
- sessionDictTemp = json.loads(sessionInfo)
- if sessionDictTemp.has_key('username'):
- return JsonResponse({'result': 0, 'description': u"此二维码已经登录,请请刷新二维码页面,然后重新扫码登录", 'payload': None})
- serviceCache.set(tokenId, json.dumps(sessionDict))
- return JsonOkResponse()
- @error_tolerate(logger=logger)
- def payNotify(request, pay_app_type):
- # type: (WSGIRequest, str)->HttpResponse
- """
- 充值成功后,更新余额,生成充值记录
- :param pay_app_type:
- :param request:
- :return: HttpResponse
- """
- recharge_cls_factory = lambda order_no: DealerRechargeRecord
- notifier_cls = PayManager().get_notifier(pay_app_type = pay_app_type)
- response = notifier_cls(request, recharge_cls_factory).do(post_pay)
- return response
- def getUserStatistics(request):
- dealer = request.user
- nowTime = datetime.datetime.now()
- dataList = []
- lastYearThisMonth = (nowTime - datetime.timedelta(days=210)).strftime('%Y-%m')
- thisMonth = nowTime.strftime('%Y-%m')
- # TODO 历史数据库整改
- rcds = DealerMonthlyStat.get_collection().find({'dealerId':dealer.id, 'date':{'$gte':lastYearThisMonth, '$lte':thisMonth}}, {'addedUserCount':1, 'date':1})
- if rcds.count == 0:
- dataList.append({'date':thisMonth, 'userAddedThisMonth':0})
- else:
- for rcd in rcds:
- dataList.append({'date':rcd['date'], 'userAddedThisMonth':rcd.get('addedUserCount', 0)})
- userCount, maleUserCount, femaleUserCount, unmaleUserCount = 0, 0, 0, 0
- allChargedMoney, allConsumeCoins, allLeftCoins = RMB(0.0), VirtualCoin(0.0), VirtualCoin(0.0)
- groupIds = Group.get_group_ids_of_dealer(str(dealer.id))
- userRcds = MyUser.objects.filter(groupId__in=groupIds).only('openId', 'sex', 'total_recharged', 'total_consumed', 'balance')
- openIdDict = {}
- for rcd in userRcds:
- openId = rcd.openId
- if not openIdDict.has_key(openId):
- openIdDict[openId] = rcd.sex
- allChargedMoney += rcd.total_recharged
- allConsumeCoins += rcd.total_consumed
- allLeftCoins += rcd.balance
- for openId, sex in openIdDict.items():
- if sex == 0:
- femaleUserCount += 1
- elif sex == 1:
- maleUserCount += 1
- else:
- unmaleUserCount += 1
- userCount += 1
- return JsonOkResponse(payload = {'userCount':userCount,'maleUserCount':maleUserCount,
- 'femaleUserCount':femaleUserCount,'unmaleUserCount':unmaleUserCount,
- 'allChargedMoney':allChargedMoney,'allConsumeCoins':allConsumeCoins,
- 'allLeftCoins':allLeftCoins,'userAddedList':dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getElecFeeConf(request):
- # payload = json.loads(request.body)
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- # ids = [ObjectId(_.id) for _ in payload.get('ids',[])]
- groups = Group.objects.filter(ownerId=str(request.user.bossId))
- total = groups.count()
- dataList = []
- for data in groups.paginate(pageIndex=pageIndex, pageSize=pageSize):
- dataList.append(
- {'elecFee':data.otherConf.get('elecFee'), # 每度多少元
- 'devElec':data.otherConf.get('devElec'), # 平均每台机器待机一天多少度
- 'groupName':data.groupName,
- 'groupId':str(data.id)
- }
- )
- return JsonOkResponse(payload={'total':total, 'dataList':dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def setElecFeeConf(request):
- payload = json.loads(request.body)
- elecFee = payload.get('elecFee')
- devElec = payload.get('devElec', 0)
- groupIds = payload.get('groupId', [])
- for groupId in groupIds:
- try:
- group = Group.objects.get(id=groupId)
- group.otherConf['elecFee'] = elecFee
- group.otherConf['devElec'] = devElec
- group.save()
- except Exception, e:
- return JsonErrorResponse(description=u'系统错误,请您重试')
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getMessage(request):
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- objs = DealerMessage.objects.filter(ownerId=str(request.user.bossId))
- total = objs.count()
- dataList = []
- for obj in objs.paginate(pageIndex=pageIndex, pageSize=pageSize):
- dataList.append({
- 'id':str(obj.id),
- 'createTime':obj.dateTimeAdded.strftime(Const.DATETIME_FMT),
- 'read':obj.read,
- 'type':obj.messageType,
- 'title':obj.title,
- 'description':obj.desc
- })
- return JsonOkResponse(payload={'total':total, 'dataList':dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def messageRead(request):
- ids = [ObjectId(_) for _ in json.loads(request.body).get('id', [])]
- DealerMessage.get_collection().update({'_id':{'$in':ids}}, {'$set':{'read':True}}, multi=True)
- # 目前需要把投诉的状态修改下
- objs = DealerMessage.objects.filter(id__in=ids)
- for obj in objs:
- if obj.messageType == 'complaint' and (obj.relatedInfo.has_key('complaintId')):
- try:
- comObj = Complaint.objects.get(id=obj.relatedInfo['complaintId'])
- comObj.handledStatus = 'notice'
- comObj.save()
- except Exception, e:
- continue
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getDeviceForMap(request):
- dealerId = str(request.user.bossId)
- statusDict = {
- str(Const.DEV_WORK_STATUS_IDLE):u'空闲',
- str(Const.DEV_WORK_STATUS_WORKING):u'繁忙工作',
- str(Const.DEV_WORK_STATUS_FAULT):u'故障',
- str(Const.DEV_WORK_STATUS_FORBIDDEN):u'禁用',
- str(Const.DEV_WORK_STATUS_PAUSE):u'暂停',
- str(Const.DEV_WORK_STATUS_FINISHED):u'充电完成',
- str(Const.DEV_WORK_STATUS_MAINTENANCE):u'设备维护中',
- str(Const.DEV_WORK_STATUS_APPOINTMENT):u'设备预约中',
- str(Const.DEV_WORK_STATUS_CONNECTED):u'正在连接车辆'
- }
- groupIds = Group.get_group_ids_of_dealer(dealerId)
- devicesDict = Device.get_devices_by_group(groupIds)
- groupDict = Group.get_groups_by_group_ids(groupIds)
- items = []
- devNos = []
- for devNo, devInfo in devicesDict.items():
- if devInfo is None or not devInfo.lbs:
- continue
- if not groupDict.has_key(devInfo['groupId']):
- continue
- group = groupDict.get(devInfo['groupId'])
- devInfo.update(
- {
- 'groupName':group['groupName'],
- 'groupNumber':devInfo['groupNumber'],
- 'address':group['address'],
- 'process':statusDict.get(devInfo['status']),
- 'type':devInfo.get('devType', {}).get('name', ''),
- 'devTypeCode':devInfo.get('devType', {}).get('code', '')
- }
- )
- devNos.append(devNo)
- items.append(devInfo)
- dev_ctrl_map = Device.get_many_dev_control_cache(devNos)
- for item in items:
- # 换电柜的端口显示可用电池数量
- if item['devTypeCode'] in [Const.DEVICE_TYPE_CODE_CHARGING_AQKJ]:
- dev_ctrl_info = dev_ctrl_map.get(device_control_cache_key(item['devNo']), {})
- item["canUseBattery"] = dev_ctrl_info.get("canUseBattery", 0)
- elif Const.DEVICE_TYPE_CODE_CHARGING_KYXN <= item['devTypeCode'] < Const.DEVICE_TYPE_CODE_WASHER_BASE:
- dev_ctrl_info = dev_ctrl_map.get(device_control_cache_key(item['devNo']), {})
- item['allPorts'] = dev_ctrl_info.get('allPorts', 10)
- item['usedPorts'] = dev_ctrl_info.get('usedPorts', 0)
- item['usePorts'] = dev_ctrl_info.get('usePorts', 10)
- if 'power' in dev_ctrl_info:
- item['power'] = dev_ctrl_info['power']
- payload = {
- 'total': len(items),
- 'items': items
- }
- return JsonOkResponse(payload=payload)
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def blackUser(request):
- """
- 汉航云充 需求 拉黑用户,用户登陆的时候做拉黑检测
- 返现被拉黑的 直接跳转拉黑界面
- :param request:
- :return:
- """
- data = json.loads(request.body)
- openId = data.get("openId", "")
- reason = data.get("reason", "")
- status = data.get("status", "black")
- dealerId = str(request.user.bossId)
- operId = str(request.user.id)
- if status not in BlackListUsers.Status.choices():
- return JsonErrorResponse(description=u"参数错误,无法拉黑用户")
- groupIds = Group.get_group_ids_of_dealer(dealerId)
- user = MyUser.objects.filter(openId=openId, groupId__in=groupIds)
- if not user:
- return JsonErrorResponse(description=u"未找到该用户!")
- # 拉黑用户操作
- if status == BlackListUsers.Status.BLACK:
- BlackListUsers.add_black_user(
- openId=openId,
- dealerId=dealerId,
- operator=operId,
- reason=reason
- )
- elif status == BlackListUsers.Status.WHITE:
- BlackListUsers.freed_black_user(
- openId=openId,
- dealerId=dealerId
- )
- else:
- return JsonErrorResponse()
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getCardPwd(request):
- dealerId = str(request.user.bossId)
- payload = json.loads(request.body)
- logicalCodes = payload.get('logicalCode')
- if len(logicalCodes) <= 0:
- return JsonErrorResponse(description=u"参数错误")
- dev = Device.get_dev_by_l(logicalCodes[0])
- if dev.ownerId != dealerId:
- return JsonErrorResponse(description=u"参数错误")
- if request.user.role != ROLE.dealer:
- return JsonErrorResponse(description=u"只能管理后台主账号才有此权限")
- box = ActionDeviceBuilder.create_action_device(dev)
- try:
- result = box.get_card_pwd()
- except ServiceException, e:
- return JsonResponse(
- {'result': 0, 'description': u'%s' % (e.result.get('description', '')), 'payload': {}})
- return JsonOkResponse(payload={'card_pwd':result['card_pwd']})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def setCardPwd(request):
- dealerId = str(request.user.bossId)
- payload = json.loads(request.body)
- cardPwd = payload.get('card_pwd')
- logicalCodes = payload.get('logicalCode')
- if len(logicalCodes) <= 0:
- return JsonErrorResponse(description=u"参数错误")
- dev = Device.get_dev_by_l(logicalCodes[0])
- if dev.ownerId != dealerId:
- return JsonErrorResponse(description=u"参数错误")
- if request.user.role != ROLE.dealer:
- return JsonErrorResponse(description=u"只能管理后台主账号才有此权限")
- box = ActionDeviceBuilder.create_action_device(dev)
- try:
- box.set_card_pwd(cardPwd)
- except ServiceException, e:
- return JsonResponse(
- {'result': 0, 'description': u'设置参数遇到错误:%s' % (e.result.get('description', '')), 'payload': {}})
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def setCardMode(request):
- dealerId = str(request.user.bossId)
- payload = json.loads(request.body)
- logicalCodes = payload.get('logicalCode')
- if len(logicalCodes) <= 0:
- return JsonErrorResponse(description=u"参数错误")
- dev = Device.get_dev_by_l(logicalCodes[0])
- if dev.ownerId != dealerId:
- return JsonErrorResponse(description=u"参数错误")
- box = ActionDeviceBuilder.create_action_device(dev)
- try:
- box.set_card_mode(payload)
- except ServiceException, e:
- return JsonResponse(
- {'result': 0, 'description': u'设置参数遇到错误:%s' % (e.result.get('description', '')), 'payload': {}})
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getCardMode(request):
- dealerId = str(request.user.bossId)
- payload = json.loads(request.body)
- logicalCodes = payload.get('logicalCode')
- if len(logicalCodes) <= 0:
- return JsonErrorResponse(description=u"参数错误")
- dev = Device.get_dev_by_l(logicalCodes[0])
- if dev.ownerId != dealerId:
- return JsonErrorResponse(description=u"参数错误")
- box = ActionDeviceBuilder.create_action_device(dev)
- try:
- result = box.get_card_mode()
- except ServiceException, e:
- return JsonResponse(
- {'result': 0, 'description': u'%s' % (e.result.get('description', '')), 'payload': {}})
- return JsonOkResponse(payload=result)
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getDealerOrderAddr(request):
- dealer = Dealer.objects.get(id=request.user.bossId)
- return JsonOkResponse(payload={'dataList':dealer.get_addr_list()})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def updateDealerOrderAddr(request):
- payload = json.loads(request.body)
- dealer = Dealer.objects.get(id=request.user.bossId)
- name = payload['name']
- tel = payload['tel']
- addr = payload['addr']
- default = payload['default']
- if payload.has_key('id') and payload['id']:
- addrs = dealer.get_addr_list()
- newList = []
- for va in addrs:
- if va['id'] == payload['id']:
- newList.append(DealerAddr(name=name, tel=tel, addr=addr, default=default, id=va['id']))
- elif default:
- newList.append(DealerAddr(name=va['name'], tel=va['tel'], addr=va['addr'], default=False, id=va['id']))
- else:
- newList.append(DealerAddr(name=va['name'], tel=va['tel'], addr=va['addr'], default=va['default'], id=va['id']))
- dealer.expressAddrList = newList
- dealer.save()
- elif not default:
- da = DealerAddr(name=name, tel=tel, addr=addr, default=default, id=str(uuid.uuid4()))
- dealer.expressAddrList.append(da)
- dealer.save()
- else:
- addrs = dealer.get_addr_list()
- newList = [DealerAddr(name=name, tel=tel, addr=addr, default=default, id=str(uuid.uuid4()))]
- for va in addrs:
- newList.append(DealerAddr(name=va['name'], tel=va['tel'], addr=va['addr'], default=False, id=va['id']))
- dealer.expressAddrList = newList
- dealer.save()
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getPartInfo(request):
- # payload = json.loads(request.body)
- logicalCode = request.GET.get('logicalCode', None)
- parts = Part.objects.filter(logicalCode=logicalCode, partName__in=[u'刷卡板', u'充电板', u'网络板'])
- result = []
- for part in parts:
- result.append({'partName':part.partName, 'registerTime':part.dateTimeAdded.strftime(Const.DATETIME_FMT),
- 'SN':part.partNo, 'expiredTime':part.expiredTime.strftime(Const.DATETIME_FMT),
- 'id':str(part.id)
- })
- return JsonOkResponse(payload={'dataList':result})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getExchangeOrder(request):
- logicalCode = request.GET.get('logicalCode', None)
- order = ExchangeOrder.objects.filter(logicalCode=logicalCode, dealerStatus__ne='finished').order_by('-dateTimeAdded').first()
- if order is None:
- return JsonOkResponse(payload={})
- data = {}
- objs = Part.objects.filter(id__in=order.parts)
- data['parts'] = [{'partName':obj.partName, 'registerTime':obj.dateTimeAdded.strftime(Const.DATE_FMT), 'expiredTime':obj.expiredTime.strftime(Const.DATE_FMT), 'SN':obj.partNo} for obj in objs]
- data['statusInfo'] = order.make_status_info()
- data['pics'] = order.pics
- data['id'] = str(order.id)
- data['dateTimeAdded'] = order.dateTimeAdded.strftime(Const.DATETIME_FMT)
- data['factoryOrderNo'] = order.factoryOrderNo
- data['dealerOrderNo'] = order.dealerOrderNo
- data['factoryAddr'] = order.factoryAddr
- data['dealerAddr'] = order.dealerAddr
- data['dealerWords'] = order.dealerWords
- data['factoryWords'] = order.factoryWords
- data['dealerStatus'] = order.dealerStatus
- data['factoryStatus'] = order.factoryStatus
- return JsonOkResponse(payload=data)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'系统开小差了,请重刷新页面,然后重试'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def updateExchangeOrder(request):
- payload = json.loads(request.body)
- if payload.has_key('id'):
- order = ExchangeOrder.objects.get(id=payload['id'])
- if payload.has_key('pics'):
- order.pics = payload.get('pics', '')
- if payload.has_key('dealerOrderNo'):
- order.dealerOrderNo = payload.get('dealerOrderNo', '')
- order.dealerStatus = 'sended'
- if payload.has_key('parts'):
- if len(payload['parts']) == 0:
- return JsonErrorResponse(description=u'必须选择一个组件哦')
- order.parts = [ObjectId(_) for _ in payload['parts'] ]
- if payload.has_key('dealerWords'):
- order.dealerWords = payload.get('dealerWords', '')
- if payload.has_key('dealerAddr'):
- order.dealerAddr = payload.get('dealerAddr',)
- order.save()
- else:
- if len(payload['parts']) == 0:
- return JsonErrorResponse(description=u'必须选择一个组件哦')
- dealerId = request.user.bossId
- dealer = Dealer.objects.get(id=dealerId)
- agent = Agent.objects.get(id=dealer.agentId)
- factoryId = agent.managerId
- order = ExchangeOrder(
- factoryId=ObjectId(factoryId),
- agentId=ObjectId(agent.id),
- ownerId=ObjectId(dealerId),
- logicalCode=payload.get('logicalCode'),
- pics=payload.get('pics', []),
- dealerOrderNo=payload.get('dealerOrderNo', ''),
- parts=[ ObjectId(_) for _ in payload['parts'] ],
- dealerWords=payload.get('dealerWords', ''),
- dealerStatus='created',
- dealerAddr=payload['dealerAddr'],
- factoryAddr=Manager.get_factory_addr(factoryId),
- )
- order.save()
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def cancelOrder(request):
- payload = json.loads(request.body)
- orderNo = payload['id']
- order = ExchangeOrder.objects.get(id=orderNo)
- if order.factoryStatus in ['sended', 'closed']:
- return JsonOkResponse(description=u'售后中心已经处理,当前不允许取消,请联系技术支持解决')
- ExchangeOrder.objects.get(id=orderNo).delete()
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def finishedOrder(request):
- payload = json.loads(request.body)
- orderNo = payload['id']
- order = ExchangeOrder.objects.get(id=orderNo)
- if order.factoryStatus in ['sended', 'closed']:
- return JsonOkResponse(description=u'售后中心已经处理,当前不允许取消,请联系技术支持解决')
- order.dealerStatus = 'finished'
- order.save()
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def deleteAddress(request):
- payload = json.loads(request.body)
- dealer = Dealer.objects.get(id=request.user.bossId)
- addrs = dealer.get_addr_list()
- newList = []
- deleteVa = None
- for va in addrs:
- if va['id'] == payload['id']:
- deleteVa = va
- continue
- else:
- newList.append(DealerAddr(name=va['name'], tel=va['tel'], addr=va['addr'], default=va['default'], id=va['id']))
- if deleteVa and deleteVa['default'] and len(newList) > 0:
- newList[0].default = True
- dealer.expressAddrList = newList
- dealer.save()
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getDevicePort(request): # type: (WSGIRequest)->JsonResponse
- currentDealer = request.user
- dev = Device.get_dev_by_logicalCode(request.GET.get('logicalCode')) # type: DeviceDict
- if str(currentDealer.id) == dev.ownerId:
- isManager = True
- else:
- isManager = False
- smartBox = dev.deviceAdapter
- try:
- # 先从设备上取信息,然后从缓存中取信息
- portDict = smartBox.dealer_get_port_status()
- except ServiceException as e:
- logger.exception(e)
- return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': None})
- except Exception as e:
- logger.exception(e)
- return JsonResponse({"result": 0, "description": u"从设备上获取端口信息失败,请您重试", "payload": {}})
- portList = []
- statsMap = {
- str(Const.DEV_WORK_STATUS_IDLE): 'idle',
- str(Const.DEV_WORK_STATUS_WORKING): 'busy',
- str(Const.DEV_WORK_STATUS_FAULT): 'fault',
- str(Const.DEV_WORK_STATUS_FORBIDDEN): 'ban',
- str(Const.DEV_WORK_STATUS_CONNECTED): 'connected',
- str(Const.DEV_WORK_STATUS_FINISHED): 'finished'
- }
- busyPortList = []
- for port, valueDict in portDict.items():
- vStatus = valueDict.get('status', None)
- if vStatus == Const.DEV_WORK_STATUS_WORKING:
- busyPortList.append(port)
- else:
- portList.append({'index': str(port), 'status': statsMap.get(str(vStatus), "idle")})
- busyPortInfoDict = smartBox.get_many_port_info(busyPortList)
- if busyPortInfoDict:
- for _info in busyPortInfoDict.values():
- if _info['status'] == Const.DEV_WORK_STATUS_WORKING:
- _info.update({'status': statsMap[str(_info['status'])]})
- if 'needTime' in _info and str(_info['needTime']).isdigit():
- info.update({'needTime': u'%s分钟' % _info['needTime']})
- else:
- _info = {'status': 'idle', 'index': str(_info['index'])}
- portList.append(_info)
- else:
- ctrInfo = Device.get_dev_control_cache(dev.devNo)
- for port, valueDict in portDict.items():
- vStatus = valueDict.get('status', None)
- if vStatus == Const.DEV_WORK_STATUS_WORKING:
- portDetail = dev.deviceAdapter.get_port_using_detail(port, ctrInfo)
- portDetail.update({"index": str(port), "status": 'busy'})
- portList.append(portDetail)
- # 排序
- portList.sort(key=lambda x: int(x['index']) if isinstance(x['index'], str) and x["index"].isdigit() else x['index'])
- # 添加单位以及功率曲线
- showPG = dev.support_power_graph and 'showPG_in_port_detail' in dev.owner.features
- unit = dev.deviceAdapter.show_pay_unit
- for item in portList:
- item['showPG'] = showPG
- if 'coins' in item.keys():
- item["coins"] = "{} {}".format(item['coins'], unit)
- return JsonOkResponse(payload={"isManager": isManager, "portList": portList})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getTempPackages(request):
- # type: (WSGIRequest)->JsonResponse
- lc = request.GET.get('logicalCode', None)
- devNo = Device.get_devNo_by_logicalCode(lc)
- if devNo is None:
- return JsonErrorResponse(description=u"缺少参数devNo")
- dev = Device.get_dev(devNo)
- if dev is None:
- return JsonErrorResponse(description=u"找不到设备")
- if "displayTempSwitchs" in dev["otherConf"]:
- displaySwitchs = dev["otherConf"].get('displayTempSwitchs')
- else:
- displaySwitchs = {'displayCoinsSwitch': True,
- 'displayTimeSwitch': True,
- 'displayPriceSwitch': True,
- "setPulseAble": False,
- "setBasePriceAble": False}
- maxCoins = dev.get('maxCoins', 4)
- group = dev.group # type: GroupDict
- if group is None:
- return JsonErrorResponse(description=u'找不到设备')
- if group.ownerId != str(request.user.bossId):
- return JsonErrorResponse(description=u'找不到设备')
- devData = {
- 'id': devNo,
- 'maxCoins': maxCoins,
- 'isManager': True,
- 'groupName': group['groupName'],
- 'groupNumber': dev['groupNumber'],
- 'devNo': devNo,
- 'type': dev['devType']['name'],
- 'typeCode': dev['devType']['code']
- }
- if dev["devType"]["code"] in support_policy_weifule:
- try:
- if dev.deviceAdapter.support_device_package:
- payload = dev.deviceAdapter.dealer_show_package(isTemp=True)
- payload.update({"devData": devData})
- return JsonOkResponse(payload=payload)
- except ServiceException as e:
- return JsonResponse({"result": 0, "description": e.result['description'], 'payload': {'devData': devData}})
- if dev["devType"]["code"] in support_policy_device:
- try:
- if dev.deviceAdapter.support_device_package:
- payload = dev.deviceAdapter.dealer_show_package(isTemp=True)
- payload.update({"devData": devData})
- return JsonOkResponse(payload=payload)
- except ServiceException as e:
- return JsonResponse({"result": 0, "description": e.result['description'], 'payload': {'devData': devData}})
- if dev["devType"]["code"] in [Const.DEVICE_TYPE_CODE_CAR_CHANGING_JINQUE, Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_JFPG,Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_DOUB_JFPG, ]:
- if dev.deviceAdapter.support_device_package:
- payload = dev.deviceAdapter.dealer_show_package(isTemp=True)
- payload.update({"devData": devData})
- return JsonOkResponse(payload=payload)
- smartBox = ActionDeviceBuilder.create_action_device(dev)
- try:
- portDict = smartBox.dealer_get_port_status()
- if portDict:
- chargeIndex = {}
- for index, info in portDict.items():
- if info['status'] == Const.DEV_WORK_STATUS_IDLE:
- chargeIndex[index] = 'idle'
- elif info['status'] == Const.DEV_WORK_STATUS_WORKING:
- chargeIndex[index] = 'busy'
- elif info['status'] == Const.DEV_WORK_STATUS_FAULT:
- chargeIndex[index] = 'fault'
- elif info['status'] == Const.DEV_WORK_STATUS_FORBIDDEN:
- chargeIndex[index] = 'ban'
- devData.update({'chargeIndex': chargeIndex})
- except ServiceException, e:
- return JsonErrorResponse(description=e.result.get('description'))
- except Exception as e:
- logger.exception(e)
- return JsonErrorResponse(description=u'未知错误')
- tempWashConfig = dev['tempWashConfig'] if dev.get('tempWashConfig', {}) != {} else dev['washConfig']
- ruleList = []
- for packageId, rule in tempWashConfig.items():
- item = {
- 'id': packageId,
- 'name': rule['name'],
- 'coins': rule['coins'],
- 'price': rule.get('price', rule['coins']),
- 'time': rule.get('time', 20),
- 'description': rule.get('description', ''),
- 'imgList': rule.get('imgList', []),
- 'unit': rule.get('unit', u'分钟')
- }
- if rule.get('pulse'):
- item.update({
- 'pulse': rule.get('pulse'),
- })
- if rule.get('basePrice'):
- item.update({
- 'basePrice': rule.get('basePrice'),
- })
- if rule.get('billingMethod') and rule['billingMethod'] != CONSUMETYPE.BILL_AS_SERVICE:
- item.update({
- 'billingMethod': rule['billingMethod'],
- })
- if 'sn' in rule:
- item['sn'] = rule['sn']
- ruleList.append(item)
- ruleList = sorted(ruleList, key=lambda x: (x.get('sn'), x.get('id')))
- return JsonOkResponse(payload={'devData': devData, 'ruleList': ruleList, 'displaySwitchs':displaySwitchs})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'保存套餐失败'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def saveTempPackages(request):
- """
- 保存套餐
- :param request:
- :return:
- """
- curr_user = request.user # type: Union[Dealer, SubAccount]
- if not curr_user.normal:
- return JsonErrorResponse(description=u'账号异常,不能进行该操作')
- status, msg = ensure_all_fields_are_not_empty(
- {k: v for k, v in request.POST.items() if k not in ('ruleId',)})
- if not status:
- return JsonErrorResponse(description=msg)
- paras = json.loads(request.body) if request.body else {}
- if not paras:
- return JsonErrorResponse(description=u'提交数据为空')
- if paras['logicalCode'].__class__.__name__ == 'list':
- devNoList = [Device.get_devNo_by_logicalCode(lc) for lc in paras['logicalCode']]
- else:
- devNoList = [Device.get_devNo_by_logicalCode(paras['logicalCode'])]
- devDict = Device.get_dev_by_nos(devNoList)
- if not devDict:
- return JsonErrorResponse(description=u'找不到设备')
- typeCode = devDict.values()[0]['devType']['code']
- if typeCode in support_policy_weifule:
- dev = devDict.values()[0]
- if dev.deviceAdapter.support_device_package:
- try:
- dev.deviceAdapter.format_device_package(isTemp=True, **paras)
- except ServiceException as e:
- return JsonResponse({"result": 0, "description": e.result['description'], 'payload': {}})
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- elif typeCode in support_policy_device:
- dev = devDict.values()[0]
- if dev.deviceAdapter.support_device_package:
- try:
- dev.deviceAdapter.format_device_package(isTemp=True, **paras)
- except ServiceException as e:
- return JsonResponse({"result": 0, "description": e.result['description'], 'payload': {}})
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- elif typeCode in [Const.DEVICE_TYPE_CODE_CAR_CHANGING_JINQUE, Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_JFPG,Const.DEVICE_TYPE_CODE_CAR_WEIFILE_HOME_DOUB_JFPG,]:
- dev = devDict.values()[0]
- if dev.deviceAdapter.support_device_package:
- washConfig, displayTempSwitchs = dev.deviceAdapter.format_device_package(isTemp=True, **paras)
- else:
- # 解析washConfig,如果需要下发设备,解析出来setConfig
- serviceList = paras['serviceData']
- # 调整sn顺序
- for item in serviceList:
- item["sn"] = serviceList.index(item)
- displayTempSwitchs = paras.get('displaySwitchs', {'displayCoinsSwitch': True,
- 'displayTimeSwitch': True,
- 'displayPriceSwitch': True,
- 'setPulseAble': False,
- 'setBasePriceAble': False})
- washConfig, setConfig = {}, {}
- existIds = []
- for rule in serviceList:
- if 'id' in rule:
- existIds.append(rule['id'])
- for rule in serviceList:
- if rule.has_key('coins') and rule.has_key('price'):
- if not (is_number(rule['coins']) and is_number(rule['price']) and is_number(
- rule.get('time', 0))):
- return JsonErrorResponse(description=u'金币数目或者时间或者价格必须是数字')
- else:
- rule['coins'], rule['price'] = 0, 0 # 对于那种先不需要付费的,这个就直接是0
- if len(rule['name']) > 20:
- return JsonErrorResponse(description=u'套餐名字只能取1-20位')
- if 'id' in rule:
- ruleId = rule['id']
- else:
- ruleId = list(set(range(1, 10)) - set([int(ruleId) for ruleId in washConfig.keys()]) - set(existIds))[0]
- washConfig[str(ruleId)] = {
- 'name': rule['name'],
- 'coins': float(rule['coins']),
- 'price': float(rule['price']),
- 'time': float(rule.get('time', 0)),
- 'description': rule.get('description', ''),
- 'imgList': rule.get('imgList', []),
- 'unit': rule.get('unit', u'分钟')
- }
- if rule.get('pulse'):
- washConfig[str(ruleId)].update({
- 'pulse': rule.get('pulse'),
- })
- if rule.get('basePrice'):
- washConfig[str(ruleId)].update({
- 'basePrice': rule.get('basePrice'),
- })
- if rule.get('billingMethod') and rule['billingMethod'] != CONSUMETYPE.BILL_AS_SERVICE:
- washConfig[str(ruleId)].update({
- 'billingMethod': rule['billingMethod'],
- })
- # 如果设备直接可以下发套餐信息到设备,直接到设备上修改。比如串口洗衣机、串口的充电设备等
- for devNo, dev in devDict.items():
- try:
- dev['tempWashConfig'] = washConfig
- otherConf = dev.get('otherConf', {})
- otherConf['displayTempSwitchs'] = displayTempSwitchs
- Device.get_collection().update({'devNo': dev['devNo']}, {'$set': {'tempWashConfig': dev['tempWashConfig'], 'otherConf':otherConf}})
- Device.invalid_device_cache(devNo)
- except ServiceException, e:
- logger.exception('update device washconfig error=%s,devNo=%s,washConfig=%s'
- % (e, devNo, dev['washConfig']))
- return JsonErrorResponse(description=u'保存套餐遇到错误,请稍候再试')
- return JsonResponse({"result": 1, "description": None, 'payload': {}})
- @error_tolerate(logger=logger, nil=JsonOkResponse(description=u"派币失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def sendCoinsForCard(request):
- """
- 经销商 给卡派币 修改模式改为订单模式
- 卡被经销商录入的时候 由于不知道是ID卡还是IC卡 因此无法对卡进行派币
- 之前 卡派币 ---> 余额增加
- 此次修改后, 卡派币 ---> 创建一条卡的充值订单 ---> 用户靠卡 ---> 走相应的同步余额的功能(ID卡直接价钱,IC有区别) ---> 余额改变
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- cardId = payload.get("cardId")
- remark = payload.get("remark", u"经销商{}赠送".format(request.user.username))
- coins = float(payload.get("coins", 0))
- card = Card.objects(id=cardId).first()
- if card is None:
- return JsonErrorResponse(description=u'没有找到卡')
- group = Group.get_group(card.groupId) # type: GroupDict
- # 创建卡充值订单表 类型为派币
- # 卡的openId 一定会存在 用户侧绑定会有 经销商录入会有 默认值
- payload = {
- 'orderNo': str(uuid.uuid1()),
- 'openId': card.openId,
- 'money': RMB(0),
- 'coins': VirtualCoin(coins),
- 'description': remark,
- 'groupId': card.groupId,
- 'groupName': group.groupName,
- 'ownerId': group.ownerId,
- 'operator': request.user.nickname,
- 'result': 'success',
- 'via': 'sendcoin',
- 'attachParas': {
- 'cardId': card.id,
- 'cardNo': card.cardNo,
- }
- }
- record = RechargeRecord(**payload).save()
- order = CardRechargeOrder.new_one(
- openId=card.openId,
- cardId=cardId,
- cardNo=card.cardNo,
- money=RMB(0),
- coins=VirtualCoin(coins),
- group=group,
- rechargeId=record.id,
- rechargeType=u"sendCoin"
- )
- # ID 卡直接充值掉
- if card.cardType == "ID":
- balance = card.balance + order.coins
- preBalance = card.balance
- order.update_after_recharge_id_card(None, balance, preBalance)
- CardRechargeRecord.add_record(
- card=card,
- group=Group.get_group(order.groupId),
- order=order,
- )
- # 刷新卡里面的余额
- card.balance = balance
- card.lastMaxBalance = balance
- card.showBalance = balance # 微付乐一体板要用
- card.save()
- # 创建上分表
- newRcd = UpCardScoreRecord(
- cardNo=card.cardNo,
- cardId=cardId,
- ownerId=str(request.user.bossId),
- score=coins,
- address=group.groupName,
- remark=remark
- )
- newRcd.save()
- return JsonResponse({"result": 1, "description": u"派币成功", 'payload': {}})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def querySendCoinsRcd(request):
- cardId = request.GET.get('cardId', None)
- if cardId:
- objs = UpCardScoreRecord.objects.filter(cardId=cardId).order_by('-dateTimeAdded')
- else:
- objs = UpCardScoreRecord.objects.filter(ownerId=str(request.user.bossId)).order_by('-dateTimeAdded')
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- total = objs.count()
- dataList = []
- for obj in objs.paginate(pageIndex=pageIndex, pageSize=pageSize):
- dataList.append({
- 'dateTimeAdded':obj.dateTimeAdded.strftime(Const.DATETIME_FMT),
- 'score':obj.score,
- 'cardNo':obj.cardNo,
- 'cardId':obj.cardId,
- 'remark':obj.remark,
- })
- return JsonOkResponse(payload={'total':total, 'dataList':dataList})
- def setSelfRechargeCardPrice(request):
- payload = json.loads(request.body)
- rechargeCardPrice = payload['rechargeCardPrice']
- dev = Device.get_dev_by_logicalCode(payload['logicalCode'])
- group = Group.get_group(dev['groupId'])
- smartbox = ActionDeviceBuilder.create_action_device(dev)
- smartbox.remote_charge_card(int(rechargeCardPrice))
- # 蓝光卡记录, 卡不用添加在后台, 所以没有卡id
- CardRechargeRecord.add_self_card_record('languang_card_id', group, RMB(rechargeCardPrice), dev)
- return JsonOkResponse()
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取自动提现信息失败"))
- @permission_required(ROLE.dealer)
- def getAutoWithdrawConfig(request):
- dealer = request.user # type: Dealer
- payload = {
- "phone": dealer.username,
- "autoWithdrawSwitch": dealer.auto_withdraw_switch,
- "autoWithdrawBankFee": dealer.auto_withdraw_bank_fee,
- "withdrawFeeRatio": dealer.withdrawFeeRatio,
- "autoWithdrawType": dealer.auto_withdraw_type,
- "weekDay": dealer.auto_withdraw_strategy.get('value'),
- "autoWithdrawMin": dealer.auto_withdraw_min
- }
- if dealer.monitorPhone:
- payload['phone'] = dealer.monitorPhone
- cards = []
- for bankCard in WithdrawBankCard.objects(ownerId = str(dealer.id), role = dealer.role):
- cards.append({
- 'accountCode': bankCard.accountCode,
- 'accountName': bankCard.accountName,
- 'bankName': bankCard.bankName
- })
- payload.update({
- 'cards': cards
- })
- return JsonOkResponse(payload = payload)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"保存自动提现信息失败"))
- @permission_required(ROLE.dealer)
- def saveAutoWithdrawConfig(request):
- dealer = request.user
- payload = json.loads(request.body)
- autoWithdrawSwitch = payload.get("autoWithdrawSwitch")
- autoWithdrawMin = RMB(payload.get("autoWithdrawMin"))
- if autoWithdrawMin < RMB(settings.WITHDRAW_MINIMUM):
- return JsonErrorResponse(description=u"最小提现金额不能少于提现接口设置最小转账金额({}元)".format(settings.WITHDRAW_MINIMUM))
- autoWithdrawType = payload.get("autoWithdrawType")
- weekDay = int(payload.get("weekDay"))
- smsCode = payload.get("code", "")
- status, msg = dealerWithdrawSMSProvider.verify(dealer.username, smsCode)
- if not status:
- return JsonErrorResponse(msg)
- # 如果自动提现到微信 需要检测提现微信是否绑定
- if autoWithdrawType == WITHDRAW_PAY_TYPE.WECHAT:
- auth_bridge = get_wechat_auth_bridge(source=dealer, app_type=APP_TYPE.WECHAT_WITHDRAW)
- key = auth_bridge.bound_openid_key
- if not dealer.isAutoWithdrawOpenIdBound(key):
- return JsonResponse({"result": ErrorCode.AUTO_WITHDRAW_WECHAT_NOT_BIND, "description": ""})
- # 银行卡的信息不保存 每次提现的时候直接去取 防止银行卡解绑造成信息不同步
- dealer.withdrawOptions.update({
- 'autoWithdrawSwitch': autoWithdrawSwitch,
- 'autoWithdrawType': autoWithdrawType,
- 'autoWithdrawStrategy': {'type': 'asWeek', 'value': weekDay},
- 'autoWithdrawMin': autoWithdrawMin.mongo_amount,
- })
- if 'bankAccount' in payload:
- dealer.withdrawOptions.update({
- 'bankAccount': payload['bankAccount']
- })
- dealer.save()
- return JsonOkResponse(description=u'自动提现配置成功')
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取绑定信息失败"))
- @permission_required(ROLE.dealer)
- def getBoundWalletWeiXinId(request):
- """
- 获取经销商绑定后台 提现的 ID
- :param request:
- :return:
- """
- dealer = request.user
- auth_bridge = get_wechat_auth_bridge(source=dealer, app_type=APP_TYPE.WECHAT_WITHDRAW)
- key = auth_bridge.bound_openid_key
- payOpenIdInfo = dealer.get_bound_pay_info(key)
- return JsonResponse(
- {
- "result": 1,
- "description": "",
- 'payload': {
- "bound": True if payOpenIdInfo.get("openId") else False,
- "avatar": payOpenIdInfo.get("avatar"),
- "sex": payOpenIdInfo.get("sex"),
- "nickname": payOpenIdInfo.get("nickname")
- }
- })
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取验证码失败"))
- @permission_required(ROLE.dealer)
- def getBindWalletWechatSMSCode(request):
- try:
- phoneNumber = request.user.username
- agent = Agent.get_agent(request.user.agentId)
- productName = agent['productName']
- if not phoneNumber:
- return JsonResponse({'result': 0, 'description': u'手机号码为空'})
- status, msg = dealerBindWalletWechatSMSProvider.get(phoneNumber=phoneNumber,
- productName=productName,
- vendor=SysParas.get_sms_vendor(request.user.smsVendor))
- if not status:
- return JsonResponse({'result': 0, 'description': msg})
- else:
- return JsonResponse({'result': 1, 'description': ''})
- except Exception, e:
- logger.exception('unable to get %s' % e)
- return JsonResponse({'result': 0, 'description': ''})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"自动绑定失败"))
- @permission_required(ROLE.dealer)
- def verifyNewWalletWechatBinding(request):
- currentDealer = request.user # type: cast(Dealer)
- code = request.POST.get('code')
- if not code:
- return JsonErrorResponse(description=u'请输入6位验证码')
- status, msg = dealerBindWalletWechatSMSProvider.verify(phoneNumber=request.user.username, smsCode=code)
- if not status:
- return JsonErrorResponse(description=msg)
- auth_bridge = get_wechat_auth_bridge(source=currentDealer, app_type=APP_TYPE.WECHAT_WITHDRAW)
- return JsonResponse(
- {
- 'result': 1,
- 'description': None,
- 'payload': {
- 'redirect_uri': auth_bridge.generate_auth_url_user_scope(
- redirect_uri=DEALER_BIND_WALLET_WECHAT_URL)
- }
- })
- @permission_required(ROLE.dealer)
- def verifyNewWalletWechatBindingCallback(request):
- auth_code = request.GET.get('code')
- if not auth_code:
- return JsonErrorResponse(description=u'未收到code,请刷新重试')
- currentDealer = request.user
- auth_bridge = get_wechat_auth_bridge(source=currentDealer, app_type=APP_TYPE.WECHAT_WITHDRAW)
- user_info = auth_bridge.get_user_info(auth_code=auth_code)
- user_info_payload = {
- 'avatar': user_info['avatar'],
- 'sex': user_info['sex'],
- 'nickname': user_info['nickname'],
- 'openId': user_info['openId']
- }
- logger.debug('dealer(id=%s) is binding wechat for messaging, bridge=%s' % (str(request.user.bossId), auth_bridge))
- key = auth_bridge.bound_openid_key
- currentDealer.set_bound_pay_info(key, **user_info_payload)
- currentDealer.save()
- return DealerBindIdResponseRedirect(result='ok')
- @permission_required(ROLE.dealer)
- def selfRechargeCardRecords(request):
- # type: (WSGIRequest)->JsonResponse
- """
- 蓝光国际手动充卡记录查询
- :param request:
- :return:
- """
- ownerId = str(request.user.bossId)
- logicalCode = request.GET['logicalCode']
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- objs = CardRechargeRecord.objects.filter(ownerId=ownerId, logicalCode=logicalCode, cardId='languang_card_id').order_by('-dateTimeAdded')
- rcdList = []
- total = 0
- for obj in objs:
- total += 1
- rcdList.append({
- 'price': int(float(str(obj.money))),
- 'dateTimeAdded': obj.dateTimeAdded.strftime("%Y-%m-%d %H:%M:%S")
- })
- return JsonResponse({
- 'result': 1,
- 'description': None,
- 'payload': {
- 'total': total,
- 'dataList': rcdList[(pageIndex - 1) * pageSize:pageIndex * pageSize]
- }
- })
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"同步设备电池信息失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def asyncBatterySnByDevice(request):
- """
- 从设备侧同步电池编号
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- logicalCode = payload.get("logicalCode")
- dealerId = str(request.user.bossId)
- dev = Device.get_dev_by_logicalCode(logicalCode=logicalCode)
- if not dev:
- return JsonErrorResponse(description=u"未找到设备,请您确认设备逻辑码正确")
- if dev.ownerId != dealerId:
- return JsonErrorResponse(description=u"未找到设备,请您确认设备逻辑码正确")
- box = ActionDeviceBuilder.create_action_device(dev)
- if not hasattr(box, "_query_all_battery_imei"):
- return JsonErrorResponse(description=u"该设备不支持导入电池编号,请确认设备逻辑码正确")
- try:
- batteryInfo = box._query_all_battery_imei()
- except ServiceException:
- return JsonErrorResponse(description=u"读取电池信息失败,请重新试试")
- addBatteryLis = list()
- for port, batterySn in batteryInfo.items():
- try:
- battery = Battery.add_from_device(
- batterySn=batterySn,
- devNo=dev.devNo,
- port=port,
- dealerId=dealerId
- )
- except Exception as e:
- logger.exception(e)
- continue
- if not battery:
- continue
- addBatteryLis.append(batterySn)
- message = u"操作成功,此次录入的电池编号为: \n{}".format("\n".join(addBatteryLis))
- return JsonOkResponse(description=message)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"录入电池信息失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def asyncBatterySnByEnter(request):
- """
- 经销商手动录入电池编号
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- batterySn = payload.get("batterySn")
- dealerId = str(request.user.bossId)
- if not Battery.is_battery_sn_format(batterySn):
- return JsonErrorResponse(u"请输入正确的电池编号(15位数字)")
- battery = Battery.add_from_enter(batterySn=batterySn, dealerId=dealerId)
- if not battery:
- return JsonErrorResponse(description=u"请勿重复录入电池编号")
- return JsonOkResponse(description=u"录入成功\n{}".format(batterySn))
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取电池列表信息失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def batteryList(request):
- """
- 获取电池列表
- :param request:
- :return:
- """
- dealerId = str(request.user.bossId)
- pageSize = int(request.GET.get("pageSize", 10))
- pageIndex = int(request.GET.get("pageIndex", 1))
- searchKey = request.GET.get("searchKey", "")
- logicalCode = request.GET.get("logicalCode")
- data = list()
- filters = {
- "dealerId": dealerId
- }
- if logicalCode:
- dev = Device.get_dev_by_l(logicalCode)
- if not dev or dev.ownerId != dealerId:
- return JsonOkResponse(payload={"total": 0, "data": data})
- filters.update({"devNo": dev.devNo})
- query = Battery.objects.filter(**filters).search(searchKey)
- total = query.count()
- batteries = query.skip((pageIndex - 1) * pageSize).limit(pageSize)
- for battery in batteries:
- data.append(battery.to_dict())
- return JsonOkResponse(
- payload={
- "total": total,
- "dataList": data
- }
- )
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"删除电池失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def deleteBattery(request):
- """
- 删除电池
- :param request:
- :return:
- """
- dealerId = str(request.user.bossId)
- payload = json.loads(request.body)
- batterySn = payload.get("ids")
- if len(batterySn) > 1:
- return JsonErrorResponse(description=u"电池数量超限")
- result = Battery.delete_one(dealerId, batterySn[0])
- if not result:
- return JsonErrorResponse(description=u"删除电池信息失败")
- return JsonErrorResponse(description=u"电池编号<{}>删除成功".format(batterySn[0]))
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取电池定位失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def batteryPosition(request):
- """
- 经销商处查看电池的定位
- :param request:
- :return:
- """
- dealerId = str(request.user.bossId)
- batterySn = request.GET.get("batterySn", "")
- battery = Battery.get_one(dealerId=dealerId, batterySn=batterySn)
- if not battery:
- return JsonErrorResponse(description=u"未找到电池,请重新试试")
- # result = BatteryInfo().getBatteryInfo(batterySn).get(batterySn)
- result = BatteryInfo().getBatteryInfo(batterySn).get(batterySn)
- if not result:
- return JsonErrorResponse(description=u"电池定位第三方数据请求失败")
- # TODO zjl 需要对经纬度进行转换
- # TODO 前台做成了分页的形式 暂时就这样吧 后续再修改
- data = {
- "lat": result.get("lat"),
- "lng": result.get("lng"),
- "voltage": result.get("voltage")
- }
- payload = {
- "total": 1,
- "items": [data]
- }
- return JsonOkResponse(payload=payload)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置电池失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def disableBattery(request):
- """
- 经销商标记电池 被标记的电池当再次被放入的时候
- :param request:
- :return:
- """
- dealerId = str(request.user.bossId)
- payload = json.loads(request.body)
- disable = payload.get("disable")
- batterySn = payload.get("batterySn")
- print batterySn, type(batterySn)
- print disable, type(disable)
- for sn in batterySn:
- battery = Battery.get_one(dealerId, sn)
- if not battery:
- return JsonErrorResponse(description=u"未查找到电池数据,请刷新页面重试")
- battery.disable = disable
- return JsonOkResponse()
- @permission_required(ROLE.dealer)
- def createEmptyCardTicket(request):
- json_str = request.body
- json_data = json.loads(json_str)
- number = json_data.get('number')
- card_id = json_data.get('cardId')
- if not str(number).isdigit():
- return JsonErrorResponse(description=u'请输入数字!')
- if int(number) > 50:
- return JsonErrorResponse(description=u'单次发卡数量不能超过50张')
- try:
- card_model = VirtualCard.objects.get(id=card_id)
- except Exception:
- return JsonErrorResponse(description=u'读取虚拟卡失败,请重试')
- attachParas = {}
- attachParas['number'] = int(number)
- attachParas['card_id'] = card_id
- virtual_cards = VirtualCardBuilder.create_virtual_card(request.user, card_model, attachParas)
- return JsonResponse({'result': 0, 'description': '当前生成卡号:%s' % (','.join(virtual_cards))})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def bindVirtualCardToRechargeIDCard(request):
- payload = json.loads(request.body)
- virtualCardId = payload.get('virtualCardId')
- rechargeIDCardId = payload.get('rechargeIDCardId')
- if virtualCardId is None:
- return JsonErrorResponse(description=u'未找到虚拟卡ID')
- if rechargeIDCardId is None:
- return JsonErrorResponse(description=u'未找到ID实体卡')
- card = Card.objects(id=rechargeIDCardId).first()
- if card is None:
- return JsonErrorResponse(description=u'未找到ID实体卡')
- if card.boundVirtualCardId:
- return JsonErrorResponse(description=u'该卡片已绑定一张虚拟卡')
- if card.cardType != RECHARGE_CARD_TYPE.ID:
- return JsonErrorResponse(description=u'该卡不是ID卡')
- virtualCard = UserVirtualCard.objects(id=virtualCardId).first()
- if virtualCard is None:
- return JsonErrorResponse(description=u'未找到虚拟卡')
- updated = card.bind_virtual_card(virtualCard)
- res = VirtualCardBuilder.active_virtual_card(virtualCardId)
- if updated and res:
- return JsonOkResponse()
- else:
- return JsonErrorResponse(description=u'绑定失败')
- @permission_required(ROLE.dealer)
- def unbindVirtualCardToRechargeIDCard(request):
- json_str = request.body
- json_data = json.loads(json_str)
- card_id = str(json_data.get('cardId'))
- try:
- card = Card.objects.get(id=card_id)
- except Exception:
- return JsonErrorResponse(description=u'数据走丢了,请稍后再试')
- if not card.bound_virtual_card:
- return JsonErrorResponse(description=u'该卡片未绑定优惠卡券')
- res = VirtualCardBuilder.unbind_virtual_card(card)
- if res:
- return JsonOkResponse()
- else:
- return JsonErrorResponse(description=u'解绑失败,请稍后再试')
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getDeviceStockForGoods(request):
- logicalCode = request.GET.get('logicalCode', '')
- pageSize = int(request.GET.get("pageSize", 10))
- pageIndex = int(request.GET.get("pageIndex", 1))
- if not logicalCode:
- return JsonErrorResponse(description=u'参数接口错误')
- devObj = Device.objects.get(logicalCode=logicalCode)
- dataList = []
- for itemTypeId, count in devObj.stockDetailDict.items():
- try:
- itemType = ItemType.objects.get(id=itemTypeId)
- except Exception, e:
- continue
- dataList.append({
- 'quantity':count,
- 'itemId':itemTypeId,
- 'itemName':itemType.title,
- 'itemPrice':itemType.price,
- 'itemPicUrl':itemType.picUrl
- })
- return JsonOkResponse(payload={'total':len(dataList), 'dataList':dataList[(pageIndex - 1) * pageSize:pageIndex * pageSize]})
- def addGoodsForStock(request):
- payload = json.loads(request.body)
- logicalCode = payload.get('logicalCode')
- quantity = payload.get('quantity')
- itemId = payload.get('itemId')
- dev = Device.get_dev_by_l(logicalCode)
- devObj = Device.objects.get(logicalCode=logicalCode)
- oldQuantity = devObj.stockDetailDict.get(itemId, 0)
- devObj.stockDetailDict[itemId] = quantity
- try:
- devObj.save()
- except Exception, e:
- return JsonResponse({'result': 0, 'description': u'更新库存失败,请重试'})
- if quantity > oldQuantity:
- stockType = 'add'
- stockNum = quantity - oldQuantity
- elif quantity < oldQuantity:
- stockType = 'remove'
- stockNum = oldQuantity - quantity
- else:
- stockType = ''
- itemObj = ItemType.objects.get(id=itemId)
- stockTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- StockRecord.get_collection().insert(
- {'logicCode': logicalCode, 'imei': dev['devNo'], 'stockType': stockType, 'stockTime': stockTime, 'number': stockNum, 'more':itemObj.title})
- # 刷新总的数目
- allCount = 0
- for count in devObj.stockDetailDict.values():
- allCount += count
- result = Device.update_field(dev_no=devObj.devNo, update=True, quantity=allCount)
- if not result:
- return JsonResponse({'result': 0, 'description': u'更新库存失败,请重试'})
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def deleteItemStock(request):
- payload = json.loads(request.body)
- logicalCode = payload.get('logicalCode')
- itemIds = payload.get('itemIds')
- dev = Device.get_dev_by_l(logicalCode)
- devObj = Device.objects.get(logicalCode=logicalCode)
- for itemId in itemIds:
- itemObj = ItemType.objects.get(id=itemId)
- stockTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- StockRecord.get_collection().insert(
- {'logicCode': logicalCode, 'imei': dev['devNo'], 'stockType': 'remove', 'stockTime': stockTime, 'number': devObj.stockDetailDict.get(itemId, 0), 'more':itemObj.title})
- try:
- devObj.stockDetailDict.pop(itemId)
- except Exception, e:
- continue
- try:
- devObj.save()
- except Exception, e:
- return JsonResponse({'result': 0, 'description': u'更新库存失败,请重试'})
- allCount = 0
- for count in devObj.stockDetailDict.values():
- allCount += count
- result = Device.update_field(dev_no=devObj.devNo, update=True, quantity=allCount)
- if not result:
- return JsonResponse({'result': 0, 'description': u'更新库存失败,请重试'})
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def updateStockQuantityForGoods(request):
- payload = json.loads(request.body)
- logicalCode = payload.get('logicalCode')
- quantity = payload.get('quantity')
- itemIds = payload.get('itemIds')
- dev = Device.get_dev_by_l(logicalCode)
- oldQuantity = dev['quantity']
- devObj = Device.objects.get(logicalCode=logicalCode)
- for itemId in itemIds:
- devObj.stockDetailDict[itemId] = quantity
- if quantity > oldQuantity:
- stockType = 'add'
- stockNum = quantity - oldQuantity
- elif quantity < oldQuantity:
- stockType = 'remove'
- stockNum = oldQuantity - quantity
- else:
- stockType = ''
- try:
- itemObj = ItemType.objects.get(id=itemId)
- except Exception, e:
- continue
- stockTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- StockRecord.get_collection().insert(
- {'logicCode': logicalCode, 'imei': dev['devNo'], 'stockType': stockType, 'stockTime': stockTime, 'number': stockNum, 'more':itemObj.title})
- try:
- devObj.save()
- except Exception, e:
- return JsonResponse({'result': 0, 'description': u'更新库存失败,请重试'})
- allCount = 0
- for count in devObj.stockDetailDict.values():
- allCount += count
- result = Device.update_field(dev_no=devObj.devNo, update=True, quantity=allCount)
- if not result:
- return JsonResponse({'result': 0, 'description': u'更新库存失败,请重试'})
- return JsonOkResponse()
- @error_tolerate(logger=logger, nil=JsonErrorResponse(description=u"没有余额卡"))
- @permission_required(ROLE.dealer)
- def getCardListForDevice(request):
- """
- 给中山绿智做的经销商充值
- """
- logicalCode = request.GET.get("logicalCode")
- dealer = Dealer.objects(id=str(request.user.id)).first()
- if dealer is None:
- return JsonErrorResponse(description=u"设备的经销商不存在")
- devNo = Device.get_devNo_by_logicalCode(logicalCode)
- dev = Device.get_dev(devNo)
- if dev is None:
- return JsonResponse({'result': 0, 'description': u'没有找到设备', 'payload': {}})
- if dev['ownerId'] != str(request.user.bossId):
- return JsonResponse({'result': 0, 'description': u'非法操作', 'payload': {}})
- box = ActionDeviceBuilder.create_action_device(dev)
- try:
- res = box.get_no_balance_list(devNo)
- except ServiceException, e:
- logger.info('error happened, error=%s' % (e,))
- return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}})
- except Exception, e:
- logger.exception('error happened, error=%s' % (e,))
- return JsonResponse({'result': 0, 'description': u'系统异常,请检查输入参数,或者稍后重试', 'payload': {}})
- return JsonResponse({'result': 1, 'description': None, 'payload': {"total":1, "dataList":res}})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(description=u"没有余额卡"))
- @permission_required(ROLE.dealer)
- def chargeInsufficientBalanceCard(request):
- """
- 给中山绿智做的经销商充值
- """
- payload = json.loads(request.body)
- logicalCode = payload.get("logicalCode")
- amount = payload.get("amount")
- cardIds = payload.get("cardIds")
- if not logicalCode or not amount or not cardIds:
- return JsonErrorResponse(description=u"请完整的传入参数")
- dealer = Dealer.objects(id=str(request.user.id)).first()
- if dealer is None:
- return JsonErrorResponse(description=u"设备的经销商不存在")
- devNo = Device.get_devNo_by_logicalCode(logicalCode)
- dev = Device.get_dev(devNo)
- if dev is None:
- return JsonResponse({'result': 0, 'description': u'没有找到设备', 'payload': {}})
- if dev['ownerId'] != str(request.user.bossId):
- return JsonResponse({'result': 0, 'description': u'非法操作', 'payload': {}})
- box = ActionDeviceBuilder.create_action_device(dev)
- try:
- res = box.remote_charge_ic_card_by_dealer(cardIds, amount)
- except ServiceException, e:
- logger.info('error happened, error=%s' % (e,))
- return JsonResponse({'result': 0, 'description': e.result.get('description'), 'payload': {}})
- except Exception, e:
- logger.exception('error happened, error=%s' % (e,))
- return JsonResponse({'result': 0, 'description': u'系统异常,请检查输入参数,或者稍后重试', 'payload': {}})
- return JsonResponse({'result': 1, 'description': None})
- @permission_required(ROLE.dealer)
- def getDeviceLocker(request):
- """
- 储物柜的大小格子配置
- """
- logicalCode = request.GET.get("logicalCode[]")
- if isinstance(logicalCode, (str, unicode)):
- dev = Device.objects.filter(logicalCode=logicalCode).first()
- sizeInfo = dev.otherConf.get("sizeInfo", [])
- if not sizeInfo:
- for i in xrange(1, 25):
- item = {"port":str(i), "size":"small"}
- sizeInfo.append(item)
- dev.otherConf["sizeInfo"] = sizeInfo
- dev.save()
- dev.invalid_device_cache(dev.devNo)
- return JsonResponse({
- "result": 1,
- "description": "",
- "payload": {
- "dataList": sizeInfo
- }
- })
- else: # 批量获取
- pass
- @permission_required(ROLE.dealer)
- def saveDeviceLocker(request):
- """
- 储物柜的大小格子配置
- """
- payload = json.loads(request.body)
- logicalCodes = payload.get("logicalCode")
- portList = payload.get("portList")
- for item in portList:
- item["port"] = str(item["port"])
- if not logicalCodes:
- return JsonResponse({"result": 2,
- "description": "设备号错误,请重试......", })
- if not portList:
- return JsonResponse({"result": 2,
- "description": "当前没有设置任何设备参数", })
- for item in logicalCodes:
- dev = Device.objects.filter(logicalCode=item).first()
- dev.otherConf["sizeInfo"] = portList
- dev.otherConf["actualPortNum"] = len(portList)
- dev.save()
- Device.invalid_device_cache(dev.devNo)
- return JsonResponse({"result": 1,
- "description": "", })
- # 经销商获取提现短信验证码
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getEditMonitorCode(request):
- # type: (WSGIRequest)->JsonResponse
- currentDealer = request.user # type: Dealer
- if currentDealer.abnormal:
- return JsonErrorResponse(description=u'该帐号资金异常,请合法经营。具体请联系客服')
- toNumber = request.GET.get('phone')
- if not toNumber:
- toNumber = request.user.monitorPhone
- if not toNumber:
- return JsonErrorResponse(description=u'没有找到提现审批人的手机号')
- agentId = request.user.agentId
- agent = Agent.get_agent(agentId)
- productName = agent['productName']
- status, msg = dealerEditMonitorSMSProvider.get(phoneNumber=toNumber,
- productName=productName,
- vendor=SysParas.get_sms_vendor(request.user.smsVendor))
- if not status:
- return JsonErrorResponse(description=msg)
- else:
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getDealerMonitor(request):
- return JsonOkResponse(payload={'phone':request.user.monitorPhone if request.user.monitorPhone else None})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def editMonitor(request):
- dealer = request.user
- if request.GET.get('oper') == 'delete':
- code = request.GET.get('code')
- phone = dealer.monitorPhone
- if not phone:
- return JsonErrorResponse(description=u'没有找到提现审批人的手机号,无法清除')
- status, msg = dealerEditMonitorSMSProvider.verify(phone, code)
- if not status:
- return JsonErrorResponse(msg)
- dealer.monitorPhone = ''
- dealer.save()
- return JsonOkResponse()
- if not request.GET.get('phone'):
- return JsonErrorResponse(description=u'没有找到提现审批人的手机号')
- phone = request.GET.get('phone')
- code = request.GET.get('code')
- status, msg = dealerEditMonitorSMSProvider.verify(phone, code)
- if not status:
- return JsonErrorResponse(msg)
- dealer.monitorPhone = phone
- dealer.save()
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def bindParentNode(request):
- payload = json.loads(request.body)
- parentNode = payload.get("parentLogicalCode")
- node = payload.get("childLogicalCode")
- category = payload.get("category")
- try:
- if category == "CM":
- # 诚马的插座 采用主绑定从的方式 进行绑定
- master, sub = Device.get_dev_by_l(parentNode), Device.get_dev_by_l(node)
- if not all([master, sub]):
- return JsonErrorResponse(description=u"绑定设备错误(10001)")
- master.deviceAdapter.add_node(sub)
- elif category == "BL":
- # 这里有3种情况,1、插座和网关一体板,自己绑自己;2、其他插座绑定纯网关的逻辑编码;3、其他插座绑一体板的二维码
- gatewayDev = Device.get_dev_by_l(parentNode) # type: DeviceDict
- if gatewayDev is None:
- Device.get_collection().update({'logicalCode':node}, {'$set':{'gateImei':parentNode}})
- gatewayPlugDev = Device.get_dev_by_l(node)
- box = gatewayPlugDev.deviceAdapter
- box.add_node(gatewayPlugDev['devNo'])
- else:
- box = gatewayDev.deviceAdapter # type: ChargingGatewayBox
- box.add_node(Device.get_dev_by_l(node)['devNo'])
- else:
- return JsonErrorResponse(description=u"错误的节点绑定类型")
- except ServiceException as se:
- return JsonErrorResponse(description=se.result["description"])
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def unbindParentNode(request):
- payload = json.loads(request.body)
- node = payload.get("logicalCode")
- nodeDev = Device.get_dev_by_l(node) # type: DeviceDict
- box = nodeDev.deviceAdapter # type: ChargingBox
- box.remove_from_gateway()
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getGateway(request):
- payload = json.loads(request.body)
- lc = payload.get("logicalCode")
- devObj = Device.objects.get(logicalCode=lc)
- if devObj.gatewayNode == '':
- return JsonResponse({"result": 1, "description": "", "payload": {}})
- gatewayDev = Device.get_dev(devObj.gatewayNode) # type: DeviceDict
- box = gatewayDev.deviceAdapter # type: ChargingGatewayBox
- devInfo = box.get_signal()
- data = {
- 'logicalCode':gatewayDev['logicalCode'],
- 'gatewaySignal':devInfo['signal'],
- 'groupName':gatewayDev['groupName']
- }
- return JsonResponse({"result": 1, "description": "", "payload": data})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getNodeList(request):
- """
- 获取主机的节点列表
- """
- lc = request.GET.get("logicalCode")
- dev = Device.get_dev_by_l(lc) # type: DeviceDict
- box = dev.deviceAdapter # type: ChargingGatewayBox
- nodeList = box.get_node_list()
- dataList = []
- devDict = {}
- for node in nodeList:
- nodeDev = Device.get_dev(node['devNo']) # type: DeviceDict
- if nodeDev is None:
- continue
- if not nodeDev.is_registered:
- _temp = {
- 'id': node.devNo,
- 'groupId': "",
- 'logicalCode': nodeDev.logicalCode,
- 'devType': nodeDev.devTypeName,
- "online": nodeDev.online,
- "registered": nodeDev.is_registered,
- "signal": nodeDev.signal
- }
- else:
- _temp = {
- 'id': node.devNo,
- 'groupId': nodeDev.group.groupId,
- 'logicalCode': nodeDev.logicalCode,
- 'devType': nodeDev.devTypeName,
- "online": nodeDev.online,
- "registered": nodeDev.is_registered,
- "signal": nodeDev.signal
- }
- if nodeDev['groupId'] in devDict:
- devDict[nodeDev['groupId']].append(node)
- else:
- devDict[nodeDev['groupId']] = [node]
- dataList.append(node)
- natural_sort(array=dataList, key='logicalCode', reverse=False)
- return JsonResponse({
- "result": 1,
- "description": None,
- 'payload': {
- "total": len(dataList),
- "groupCount": len(devDict.keys()),
- "dataList": dataList
- }
- })
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getPortParam(request):
- payload = json.loads(request.body)
- lc = payload.get("logicalCode")[0]
- portIndex = payload.get("port")
- dev = Device.get_dev_by_l(lc) # type: DeviceDict
- box = dev.deviceAdapter # type: ChargingBox
- config = box.get_port_config(portIndex)
- return JsonResponse({"result": 1, "description": "", "payload": config})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def setPortParam(request):
- payload = json.loads(request.body)
- lc = payload.get("logicalCode")[0]
- portIndex = payload.get("port")
- maxCurrent = payload.get('max_current', 10)
- maxPower = payload.get('max_power', 1000)
- dev = Device.get_dev_by_l(lc) # type: DeviceDict
- box = dev.deviceAdapter # type: ChargingBox
- box.set_port_config(portIndex, {'max_power':int(maxPower), 'max_current':int(maxCurrent)})
- return JsonOkResponse()
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def beAuthLogin(request):
- oper_id = request.GET.get('dealerId')
- # 校验经销商是否存在
- dealer = Dealer.objects.filter(id=oper_id).first()
- if not dealer:
- return ErrorResponseRedirect(error=cn('当前经销不存在'))
- # 校验当前用户是否已经是授权登入的
- session = DealerSessionBuilder(request)
- if session.is_dealer_trustee():
- return ErrorResponseRedirect(error=cn('授权人页面不允许切换'))
- role = PermissionRole.objects.filter(dealerId=str(dealer.id), operId=str(request.user.id)).first()
- if role:
- if role.isActive:
- session.check_out_to_dealer_trustee(oper_id)
- else:
- if role.authorizeType == 'dealer_to_dealer':
- return ErrorResponseRedirect(error=cn(u'请联系您的授权经销商给您配置权限'))
- elif role.authorizeType == 'dealer_to_subAccount':
- return ErrorResponseRedirect(error=cn(u'请联系您的主经销商同意此授权关系'))
- else:
- # 没有权限
- return ErrorResponseRedirect(error=cn(u'当前授权已失效'))
- return FrontEndResponseRedirect(add_query('/app/index.html', {}))
- @permission_required(ROLE.dealer)
- def loginMyPrimaryAccount(request):
- session = DealerSessionBuilder(request)
- if session.is_dealer_trustee():
- result = session.check_out_to_dealer_master()
- if not result:
- return ErrorResponseRedirect(error=cn(u'验证失败,请重新登入'))
- else:
- pass
- # return ErrorResponseRedirect(error=cn(u'当前已经是主账户'))
- # 无需切换已经是主账户
- return FrontEndResponseRedirect(add_query('/app/index.html', {}))
- @permission_required(ROLE.dealer)
- def addOrEditOperatorPermission(request):
- session = DealerSessionBuilder(request)
- if session.is_dealer_trustee():
- # 操作员无权限修改改权限
- return ErrorResponseRedirect(error=cn(u'您当前无权修改授权权限'))
- else:
- permissionId = request.POST.get('permissionId')
- permissionDict = request.POST.get('permissions')
- PermissionRule.objects.get(id=permissionId, dealerId=str(request.user.id)).update(permissionDict=permissionDict)
- @permission_required(ROLE.dealer)
- def getAccountPermissionByAuthId(request):
- id = request.GET.get('id')
- role = PermissionRole.objects.filter(operId=id, dealerId=str(request.user.id)).first()
- if not role:
- return JsonResponse({'result': 0, 'description': '您的当前授权已失效'})
- rule = PermissionRule.objects.filter(id=role.permissionRuleId).first()
- return JsonResponse({'result': 1, 'description': '', 'payload': rule.get_permissionDict()})
- @permission_required(ROLE.dealer)
- def saveAccountPermissionByAuthId(request):
- payload = json.loads(request.body)
- id = payload.pop('id', None)
- role = PermissionRole.objects.filter(operId=id, dealerId=str(request.user.id)).first()
- if role:
- if role.authorizeType == 'dealer_to_dealer': # 经销商对经销商 直接激活此次授权
- role.update(isActive=True)
- elif role.authorizeType == 'dealer_to_subAccount': # 经销商对子账号 需要子账号的主账号同意
- pass
- rule = PermissionRule.objects.filter(id=role.permissionRuleId).update(permissionDict=payload)
- return JsonResponse({'result': 1, 'description': '', 'payload':{}})
- else:
- return JsonResponse({'result': 0, 'description': '权限配置失败', 'payload': {}})
- @permission_required(ROLE.dealer)
- def getAuthList(request):
- dealer_id = PermissionRole.get_auth_to_dealer(dealerId=str(request.user.id))
- dealers = Dealer.objects(id__in=dealer_id)
- total = dealers.count()
- pageSize = int(request.GET.get('pageSize', 10))
- pageIndex = int(request.GET.get('pageIndex', 1))
- dataList = []
- for dealer in dealers:
- item = {
- 'id': str(dealer.id),
- 'nickname': dealer.nickname,
- 'username': dealer.username,
- 'avatarUrl': dealer.my_avatar if dealer.my_avatar else settings.DEFAULT_AVATAR_URL,
- }
- dataList.append(item)
- subAccount_id = PermissionRole.get_auth_to_sub(dealerId=str(request.user.id))
- subAccounts = SubAccount.objects(id__in=subAccount_id)
- total += subAccounts.count()
- for subAccount in subAccounts:
- item = {
- 'id': str(subAccount.id),
- 'nickname': subAccount.nickname,
- 'username': subAccount.username,
- 'avatarUrl': subAccount.my_avatar if subAccount.my_avatar else settings.DEFAULT_AVATAR_URL,
- }
- dataList.append(item)
- payload = {
- 'total': total,
- 'dealerId': str(request.user.id),
- 'agentId': request.user.agentId,
- 'dataList': dataList[pageIndex * pageSize - pageSize: pageIndex * pageSize ]
- }
- return JsonResponse({'result': 1, 'description': '', 'username':request.user.username, 'payload': payload})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getBeAuthList(request):
- if request.user.role == 'dealer':
- dealer_id = PermissionRole.get_is_auth_list(operId=str(request.user.id), authorizeType='dealer_to_dealer')
- elif request.user.role == 'subaccount':
- dealer_id = PermissionRole.get_is_auth_list(operId=str(request.user.id), authorizeType='dealer_to_subAccount')
- else:
- return ErrorResponseRedirect(error=cn(u'您无权限进行此操作'))
- dealers = Dealer.objects(id__in=dealer_id)
- total = dealers.count()
- payload = {
- 'total': total,
- 'dealerId': str(request.user.id),
- 'agentId': request.user.agentId
- }
- pageSize = int(request.GET.get('pageSize', 10))
- pageIndex = int(request.GET.get('pageIndex', 1))
- dataList = []
- for dealer in dealers.paginate(pageIndex=pageIndex, pageSize=pageSize):
- item = {
- 'dealerId': str(dealer.id),
- 'nickname': dealer.nickname,
- 'username': dealer.username,
- 'avatarUrl': dealer.my_avatar if dealer.my_avatar else settings.DEFAULT_AVATAR_URL,
- }
- dataList.append(item)
- payload['dataList'] = dataList
- return JsonResponse({'result': 1, 'description': '', 'username': request.user.username, 'payload': payload})
- @error_tolerate(nil=DefaultJsonErrorResponse, logger=logger)
- @permission_required(ROLE.dealer)
- def getMonthlyPackageTemp(request):
- """
- 获取包月套餐
- :param request:
- :return:
- """
- dealerId = str(request.user.bossId)
- dealer = Dealer.objects.get(id=dealerId)
- monthlyPackages = dealer.monthlyPackage
- dataList = [_package.to_dict() for _package in monthlyPackages]
- return JsonOkResponse(payload={"dataList": dataList})
- @error_tolerate(nil=DefaultJsonErrorResponse, logger=logger)
- @permission_required(ROLE.dealer)
- def getMonthlyPackageTempDetail(request):
- monthlyPackageId = request.GET.get("id", "")
- monthlyPackage = MonthlyPackageTemp.get_package_by_id(monthlyPackageId)
- if not monthlyPackage or monthlyPackage.ownerId != str(request.user.bossId):
- return JsonErrorResponse(description=u"未找到相应模板套餐,请刷新重试")
- return JsonOkResponse(payload=monthlyPackage.to_dict())
- @error_tolerate(nil=DefaultJsonErrorResponse, logger=logger)
- @permission_required(ROLE.dealer)
- def saveMonthlyPackageTemp(request):
- """
- 保存包月套餐模板
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- packageId = payload.pop("id", "")
- monthlyPackage = MonthlyPackageTemp.get_package_by_id(packageId)
- if not monthlyPackage or monthlyPackage.ownerId != str(request.user.bossId):
- return JsonErrorResponse(description=u"未找到相应模板套餐,请刷新重试")
- # 修改包月的模板套餐
- monthlyPackage.update_by_fields(**payload)
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse, logger=logger)
- @permission_required(ROLE.dealer)
- def delMonthlyPackageTemp(request):
- """
- 经销商删除包月套餐模板
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- packageId = payload.get("id", "")
- monthlyPackage = MonthlyPackageTemp.get_package_by_id(packageId)
- if not monthlyPackage:
- return JsonErrorResponse(description=u"未找到相应包月模板,请刷新重试")
- if monthlyPackage.ownerId != str(request.user.bossId):
- return JsonErrorResponse(description=u"未找到相应包月模板,请刷新重试")
- # 默认模板无法删除
- if monthlyPackage.isDefault:
- return JsonErrorResponse(description=u"默认包月模板无法删除")
- # 需要将关联此模板的地址组的包月信息全部清空 置为默认的
- groupIds = Group.get_group_ids_of_dealer(str(request.user.bossId))
- Group.objects.filter(id__in=groupIds, monthlyPackage=monthlyPackage).update(monthlyPackage=None)
- # 最后将改套餐置为 idDelete
- monthlyPackage.update(isDelete=1)
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse, logger=logger)
- @permission_required(ROLE.dealer)
- def setDefaultMonthlyPackageTemp(request):
- """
- 经销商 将包月套餐设置成默认的套餐
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- packageId = payload.get("id", "")
- monthlyPackage = MonthlyPackageTemp.get_package_by_id(packageId)
- if not monthlyPackage:
- return JsonErrorResponse(description=u"未找到相应包月模板,请刷新重试")
- if monthlyPackage.ownerId != str(request.user.bossId):
- return JsonErrorResponse(description=u"未找到相应包月模板,请刷新重试")
- monthlyPackage.set_default()
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse, logger=logger)
- @permission_required(ROLE.dealer)
- def addGroupToMonthlyPackageTemp(request):
- """
- 添加设备 到 包月套餐
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- packageId = payload.get("packageId", "")
- groupIds = payload.get("groupId", "")
- groups = list()
- for _groupId in groupIds:
- group = Group.get_dealer_group(str(request.user.bossId), id=_groupId.get("groupId", ""))
- if not group:
- return JsonErrorResponse(description=u"未找到相应的设备组,请刷新重试")
- groups.append(group)
- monthlyPackage = MonthlyPackageTemp.get_dealer_package(ownerId=str(request.user.bossId), id=packageId)
- if not monthlyPackage:
- return JsonErrorResponse(description=u"未找到相应套餐,请刷新重试")
- for _group in groups:
- _group.monthlyRule = monthlyPackage
- return JsonOkResponse()
- @error_tolerate(nil=DefaultJsonErrorResponse, logger=logger)
- @permission_required(ROLE.dealer)
- def addMonthlyPackageTemp(request):
- ownerId = str(request.user.bossId)
- payload = json.loads(request.body)
- monthlyPackage = MonthlyPackageTemp.create_by_fields(ownerId=ownerId, **payload)
- return JsonOkResponse(payload={"packageId": str(monthlyPackage.id)})
- @permission_required(ROLE.dealer)
- def deleteAuth(request):
- session = DealerSessionBuilder(request)
- if session.is_dealer_trustee():
- return ErrorResponseRedirect(error=cn(u'您无权限进行此操作'))
- if request.method != 'POST':
- return ErrorResponseRedirect(error=cn(u'异常访问'))
- payload = json.loads(request.body)
- operIds = payload.get('ids')
- try:
- PermissionRole.delete_role_permission(operIds=operIds, dealerId=str(request.user.id))
- except Exception:
- return JsonResponse({'result': 0, 'description': '扫码识别失败,请重试', 'payloay':{}})
- return JsonResponse({'result': 1, 'description': '成功', 'payload':{}})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def toAuthToken(request):
- session = DealerSessionBuilder(request)
- if session.is_dealer_trustee():
- return ErrorResponseRedirect(error=cn(u'您无权限进行此操作'))
- else:
- if request.user.role == 'dealer':
- dealerId = str(request.user.id)
- payload = {'oper_id':dealerId, 'role':'dealer'}
- elif request.user.role == 'subaccount':
- subaccount = str(request.user.id)
- payload = {'oper_id': subaccount, 'role': 'subaccount'}
- else:
- return ErrorResponseRedirect(error=cn(u'您无权限进行此操作'))
- token = MyToken.encode(payload)
- logger.info(token)
- return JsonResponse({ 'result': 1, 'description': None, 'payload': {'dealerId': 'xxx', 'token': token}})
- @permission_required(ROLE.dealer)
- def getOtherDealerAuth(request):
- # 经销商扫经销商授权
- scannedURL = request.GET.get('url', None)
- if not scannedURL:
- return JsonResponse({'result': 100, 'description': u'错误的二维码或二维码已损坏'})
- from urlparse import unquote
- scannedURL = unquote(scannedURL)
- logger.debug('scan url is {}'.format(scannedURL))
- return FrontEndResponseRedirect(add_query(scannedURL, {}))
- @permission_required(ROLE.dealer)
- def toAuth(request):
- master_id = str(request.user.id)
- token = request.GET.get('token', None)
- if not token:
- return JsonResponse({'result': 0, 'description': '扫码识别失败,请重试', 'payload': {}})
- try:
- payload = MyToken.decode(token)
- except Exception as e:
- logger.info('toAuth token is invalid..')
- payload = {}
- if not payload:
- return JsonResponse({'result': 0, 'description': '二维码已失效,请重新添加二维码!!', 'payload': {}})
- role = payload.get('role')
- oper_id = payload.get('oper_id')
- if role == 'dealer':
- if PermissionRole.objects.filter(dealerId=master_id, operId=oper_id).first():
- PermissionRole.objects.filter(dealerId=master_id, operId=oper_id).update(isActive=True)
- return JsonResponse({'result': 0, 'description': '已添加授权人!!', 'payload': {}})
- else:
- PermissionRole.add_dealer_role(oper_id, master_id)
- return JsonResponse({'result': 0, 'description': '授权人添加成功', 'payload':{}})
- elif role == 'subaccount':
- if PermissionRole.objects.filter(dealerId=master_id, operId=oper_id).first():
- return JsonResponse({'result': 1, 'description': '已添加授权人!!', 'payload': {}})
- else:
- PermissionRole.add_subAccount_role(oper_id, master_id)
- return JsonResponse({'result': 1, 'description': '授权人添加成功,等待子账号主经销商同意', 'payload': {}})
- @permission_required(ROLE.dealer)
- def getSubAccountBeAuthList(request):
- subAccountId = request.GET.get('id')
- master_id = str(request.user.id)
- subAccount = SubAccount.objects.filter(id=subAccountId).first()
- if not subAccount:
- return JsonResponse({'result': 0, 'description': '扫码识别失败,请重试', 'payloay':{}})
- pageSize = int(request.GET.get('pageSize', 10))
- pageIndex = int(request.GET.get('pageIndex', 1))
- roles = PermissionRole.objects.filter(operId=subAccountId, authorizeType='dealer_to_subAccount')
- count = roles.count()
- dataList = []
- for role in roles.paginate(pageIndex=pageIndex, pageSize=pageSize):
- dealer = Dealer.objects.filter(id=role.dealerId).first()
- if dealer:
- item = {
- 'id': str(dealer.id),
- 'nickname': dealer.nickname,
- 'username': dealer.username,
- 'avatarUrl': dealer.my_avatar if dealer.my_avatar else settings.DEFAULT_AVATAR_URL,
- 'status': 'agreed' if role.isActive else '',
- }
- dataList.append(item)
- return JsonResponse({'result':1, 'username':subAccount.username, 'payload':{'dealerId':subAccount.bossId, 'agentId':subAccount.agentId, 'dataList':dataList}})
- @permission_required(ROLE.dealer)
- def agreeSubAccountBeAuth(request):
- session = DealerSessionBuilder(request)
- if session.is_dealer_trustee():
- return ErrorResponseRedirect(error=cn(u'您无权限进行此操作'))
- if request.method != 'POST':
- return ErrorResponseRedirect(error=cn(u'异常访问'))
- payload = json.loads(request.body)
- subAccountId = payload.get('subAccountId')
- authDealerId = payload.get('authDealerId')
- if not subAccountId or not authDealerId:
- return JsonResponse({'result': 1, 'description': '授权失败,请稍后再试', 'payload': {}})
- PermissionRole.objects.filter(operId=subAccountId, dealerId=authDealerId).update(isActive=True)
- return JsonResponse({'result': 1, 'description': '成功', 'payload':{}})
- @permission_required(ROLE.dealer)
- def disagreeSubAccountBeAuth(request):
- session = DealerSessionBuilder(request)
- if session.is_dealer_trustee():
- return ErrorResponseRedirect(error=cn(u'您无权限进行此操作'))
- if request.method != 'POST':
- return ErrorResponseRedirect(error=cn(u'异常访问'))
- payload = json.loads(request.body)
- subAccountId = payload.get('subAccountId')
- authDealerId = payload.get('authDealerId')
- if not subAccountId or not authDealerId:
- return JsonResponse({'result': 1, 'description': '授权失败,请稍后再试', 'payload': {}})
- PermissionRole.objects.filter(operId=subAccountId, dealerId=authDealerId).update(isActive=False)
- return JsonResponse({'result': 1, 'description': '成功', 'payload': {}})
- @permission_required(ROLE.dealer)
- def toOtherDealerAuth(request):
- # 子账号授权
- scannedURL = request.GET.get('url', None)
- if not scannedURL:
- return JsonResponse({'result': 100, 'description': u'错误的二维码或二维码已损坏'})
- from urlparse import unquote
- scannedURL = unquote(scannedURL)
- logger.debug('scan url is {}'.format(scannedURL))
- return FrontEndResponseRedirect(add_query(scannedURL, {}))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getLastVirtualCard(request):
- """
- 获取 经销商自己配置的虚拟卡的模板
- :param request:
- :return:
- """
- obj = VirtualCard.get_last(str(request.user.bossId))
- if obj:
- data = obj.to_dict()
- return JsonOkResponse(payload=data)
- else:
- data = {
- 'cardName': u"时长套餐",
- 'price': 30,
- 'periodDays': 30,
- 'expiredTime': (datetime.datetime.now() + datetime.timedelta(days=30)).strftime("%Y-%m-%d"),
- 'dealerDesc': "",
- 'userDesc': "",
- 'dayQuota': [],
- 'quota': [],
- 'sharedMembersCount': 3,
- 'userLimit': 3,
- }
- return JsonOkResponse(payload=data)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getDeviceWarning(request):
- """
- 获取设备端的告警信息
- :param request:
- :return:
- """
- logicalCode = request.GET.get("logicalCode")
- dev = Device.get_dev_by_l(logicalCode)
- if not dev:
- return JsonErrorResponse(description=u"未找到设备,请刷新重试")
- if dev.ownerId != str(request.user.bossId):
- return JsonErrorResponse(description=u"未找到设备,请刷新重试")
- warningInfo = Device.get_dev_warning_cache(dev.devNo)
- portWarning = list()
- deviceWarning = dict()
- for _part, _warning in warningInfo.items():
- if not _warning:
- continue
- _newWarning = {
- "warningPart": _part,
- "warningStatus": _warning["warningStatus"],
- "warningDesc": _warning["warningDesc"],
- "warningTime": _warning["warningTime"]
- }
- if _part.isdigit():
- portWarning.append(_newWarning)
- else:
- deviceWarning = _newWarning
- return JsonOkResponse(payload={"device": deviceWarning, "ports": portWarning})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def cancelDeviceWarning(request):
- """
- 取消设备的告警信息
- :param request:
- :return:
- """
- logicalCode = request.POST.get("logicalCode")
- part = request.POST.get("part")
- dev = Device.get_dev_by_l(logicalCode)
- if not dev:
- return JsonErrorResponse(description=u"未找到设备,请刷新重试")
- if dev.ownerId != str(request.user.bossId):
- return JsonErrorResponse(description=u"未找到设备,请刷新重试")
- if part is None:
- Device.clear_dev_warning_cache(dev.devNo)
- else:
- Device.clear_part_warning_cache(dev.devNo, part)
- return JsonOkResponse()
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def clearDeviceCache(request):
- data = json.loads(request.body)
- dev = Device.get_dev_by_logicalCode(data['logicalCode'])
- Device.invalid_all_cache(dev)
- return JsonOkResponse()
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getCurrencyGroups(request):
- """
- 获取经销商通用组以及通用模式
- :param request:
- :return:
- """
- current_user = request.user # type: Dealer
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- groups = []
- for group in Group.get_collection().find({'ownerId': str(request.user.bossId)},
- {'_id': 1, 'name': 1, 'currencyGroup': 1, 'groupName': 1}):
- if 'currencyGroup' in group:
- groups.append({
- 'groupId': str(group['_id']),
- 'groupName': group['groupName'],
- 'currencyGroup': group['currencyGroup']
- })
- groups.sort(key=itemgetter('currencyGroup'))
- dataList = []
- for currencyGroup, groups in groupby(groups, itemgetter('currencyGroup')):
- dataList.append({
- 'name': currencyGroup,
- 'members': [{'id': group['groupId'], 'name': group['groupName']} for group in groups]
- })
- return JsonOkResponse(payload={
- 'currencyMode': current_user.currency_mode,
- 'total': len(dataList),
- 'dataList': dataList[pageIndex * pageSize - pageSize: pageIndex * pageSize]
- })
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def updatCurrencyGroups(request):
- """
- 更新经销商通用组以及通用模式
- :param request:
- :return:
- """
- boss = request.user.myBoss # type: Dealer
- payload = json.loads(request.body)
- # 校验分组名字是否为'',否则会导致设置地址组通用(删除操作的时候)无法生效.
- name_list = map(lambda x: x.get('name'), payload.get('groupList', None))
- if name_list:
- check_name = None
- for name in name_list:
- if name == check_name:
- return JsonErrorResponse(description='分组名称不能相同')
- else:
- check_name = name
- else:
- pass
- # 初始化之前的组
- beforeDataList = payload.get('beforeDataList', [])
- for groupInfo in beforeDataList:
- group_ids = [ObjectId(group['id']) for group in groupInfo['members']]
- Group.objects(id__in=group_ids,
- ownerId=str(request.user.bossId)).update(currencyGroup='')
- currencyMode = payload['currencyMode']
- if boss.currencyMode != currencyMode:
- boss.update(currencyMode=currencyMode)
- Dealer.invalid_cache(str(boss.id))
- share_group_list = payload['groupList']
- for share_group in share_group_list:
- share_name = share_group['name']
- group_ids = [ObjectId(group['id']) for group in share_group['members']]
- Group.objects(id__in=group_ids,
- ownerId=str(request.user.bossId)).update(currencyGroup=share_name)
- Group.invalid_group_cache(group_ids)
- return JsonOkResponse()
- @permission_required(ROLE.dealer)
- def setSimChargeAuto(request):
- dealerId = request.user.id
- Device.get_collection().update({'ownerId':str(dealerId)}, {'$set':{'simChargeAuto':True}})
- return JsonOkResponse()
- @permission_required(ROLE .dealer)
- def activeRentDevice(request):
- """
- 经销商主动激活出租设备
- """
- payload = json.loads(request.body)
- logicalCode = payload.get("logicalCode")
- if not logicalCode:
- return JsonErrorResponse(u"激活失败")
- device = Device.objects.get(logicalCode=logicalCode)
- if not device:
- return JsonErrorResponse(u"激活失败")
- try:
- device.active_rent()
- except RentDeviceError as e:
- return JsonErrorResponse(e.message)
- return JsonOkResponse()
- @permission_required(ROLE.dealer)
- def getRentOrder(request):
- """
- 获取经销商所有的日租订单 从前往后
- """
- logicalCode = request.GET.get("logicalCode")
- pageSize = request.GET.get("pageSize")
- pageIndex = request.GET.get("pageIndex")
- if not logicalCode:
- return JsonErrorResponse(u"获取记录失败")
- device = Device.objects.get(logicalCode=logicalCode)
- if not device:
- return JsonErrorResponse(u"获取记录失败")
- orders = DeviceRentOrder.get_by_device(device)
- dataList = [_.to_dict() for _ in orders]
- return JsonOkResponse(payload={"total": orders.count(), "dataList": dataList})
- @permission_required(ROLE.dealer)
- def sendVirtualCard(request):
- payload = json.loads(request.body)
- openId = payload.get("openId")
- groupId = payload.get("groupId")
- cardId = payload.get("cardId")
- vCard = VirtualCard.objects.filter(id=cardId).first()
- if not vCard:
- return JsonErrorResponse(description=u"未找到虚拟卡,请确认虚拟卡信息后重试")
- user = MyUser.objects.filter(openId=openId, groupId=groupId).first()
- if not user:
- return JsonErrorResponse(description=u"未找到用户,请确认派卡地址是否正确")
- userCard = UserVirtualCard(
- cardNo=UserVirtualCard.make_no(),
- cardTypeId=str(cardId),
- openIds=[openId],
- cardName=vCard.cardName,
- ownerOpenId=openId,
- nickname=user.nickname,
- dealerId=vCard.ownerId,
- groupIds=vCard.groupIds,
- devTypeList=vCard.devTypeList,
- price=vCard.price,
- periodDays=vCard.periodDays,
- expiredTime=datetime.datetime.now() + datetime.timedelta(seconds=vCard.periodDays * 24 * 3600),
- dayQuota=vCard.dayQuota,
- userLimit=vCard.userLimit,
- quota=vCard.quota,
- userDesc=vCard.userDesc,
- managerialAppId=user.managerialOpenId,
- managerialOpenId=user.managerialOpenId,
- logicalCode="",
- groupId=groupId
- ).save()
- return JsonOkResponse(description=u"发卡成功")
- @permission_required(ROLE.dealer)
- def stopUserOrder(request):
- orderId = request.GET.get('orderId')
- order = ClientConsumeModelProxy.get_one(id=orderId) # type: ConsumeRecord
- if not order:
- return JsonErrorResponse(description='未找到该笔订单')
- if order.devTypeCode:
- try:
- from apps.web.core.models import DriverAdapter
- adapter = DriverAdapter.get_driver_adapter(order.devTypeCode, None)
- adapter.force_stop_order(order)
- except:
- order.update(isNormal=False, errorDesc='强制订单失败后, 直接更新订单')
- return JsonOkResponse(description=u"停止成功")
- else:
- return JsonErrorResponse(description='强制停止失败')
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getConsumeTemplate(request):
- """
- 获取用户的消费信息 模板的配置
- :param request:
- :return:
- """
- owner = request.user.myBoss # type: Dealer
- showList = owner.supportedConsumptionShow
- if not showList:
- from apps.web.common.utils import UserConsumeFilter
- showList = UserConsumeFilter.default_filter()
- return JsonOkResponse(payload = {"showList": showList})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def setConsumeTemplate(request):
- """
- 设置用户的参数
- :param request:
- :return:
- """
- dealerId = request.user.bossId
- payload = json.loads(request.body)
- try:
- Dealer.objects.get(id=dealerId).update(supportedConsumptionShow=payload["showList"])
- Dealer.invalid_cache(dealerId)
- except DoesNotExist:
- return JsonErrorResponse(u"参数错误, 请刷新重试")
- except Exception as e:
- logger.exception("update dealer <{}> supportedConsumptionShow error = {}".format(dealerId, e))
- return JsonErrorResponse(u"参数错误, 请刷新重试")
- return JsonOkResponse()
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"退款操作中出现异常,请联系客服处理"))
- @permission_required(ROLE.dealer)
- def refundOrder(request):
- payload = json.loads(request.body)
- logger.debug('dealer refund order. dealer: {}, payload: {}'.format(request.user, payload))
- orderNo = payload.get("orderNo", None)
- if not orderNo:
- return JsonErrorResponse(description=u"参数错误,请刷新页面重试")
- refundMoney = RMB(payload.get("refundMoney"))
- deductCoins = VirtualCoin(payload.get("deductCoins"))
- rechargeOrder = RechargeRecord.objects.filter(orderNo=orderNo).first() # type: RechargeRecord
- if not rechargeOrder:
- return JsonErrorResponse(description=u"未查询到订单,请刷新页面重试")
- if not rechargeOrder.is_refund_available(request.user):
- return JsonErrorResponse(description=u"该类型订单不支持退款")
- if rechargeOrder.coins < deductCoins:
- return JsonErrorResponse(description=u"扣除金币数大于用户实际购买数目")
- currency = rechargeOrder.myuser.calc_currency_balance(rechargeOrder.owner, rechargeOrder.group)
- if currency < deductCoins:
- return JsonErrorResponse(description = u"扣除金币数大于用户目前余额")
- if not rechargeOrder.is_success:
- return JsonErrorResponse(description = u"退款失败,订单状态非成功,请联系平台客服")
- if not rechargeOrder.is_ledgered:
- # 检验订单是否有收益
- return JsonErrorResponse(description=u"退款失败,订单未产生收益,请联系平台客服")
- try:
- refundedOrder = refund_cash(rechargeOrder, refundMoney, deductCoins)
- return JsonOkResponse(description=u"退款成功", payload={"refundedOrderNo": refundedOrder.orderNo})
- except ServiceException as e:
- logger.error(e.result)
- return JsonResponse(e.result)
- except UserServerException as e:
- logger.error(e.message)
- return JsonErrorResponse(description=e.message)
- except Exception as e:
- return JsonErrorResponse(description=u"退款失败,请刷新后重试")
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getDealerTodoMessage(request):
- """
- 获取经代销商的代办事项
- """
- messages = TodoMessage.get_todo_message(request.user)
- # 进行一次任务检查 查看任务是否完成以及是否需要强制执行
- return JsonOkResponse(payload={"count": len(messages), "dataList": messages})
- @permission_required(ROLE.dealer)
- def saveUserBlackConfig(request):
- dealerId = str(request.user.id)
- payload = json.loads(request.body)
- breakRuleTimes = payload.get('breakRuleTimes', 0)
- orderRemindType = payload.get('orderRemindType', 2)
- openId = payload.get('openId', '')
- dealer = Dealer.objects(id=dealerId).first()
- users = MyUser.objects(openId=openId, agentId=dealer.agentId)
- if users.count() == 0:
- return JsonErrorResponse(description=u"不存在的用户")
- for _ in users:
- _.blacklistConfig['breakRuleTimes'] = breakRuleTimes
- _.blacklistConfig['orderRemindType'] = orderRemindType
- try:
- _.save()
- except Exception as e:
- return JsonErrorResponse(description=u"系统错误")
- return JsonOkResponse(description=u"设置成功")
- @permission_required(ROLE.dealer, ROLE.subaccount)
- @ViewValidator(UserListValidator)
- def userList(request, data):
- groupId = data.get("groupId")
- source = data.get("source")
- reverse = data.get("reverse")
- searchKey = data.get("searchKey")
- pageSize = data.get("pageSize")
- pageIndex = data.get("pageIndex")
- userQuery = MyUser.objects.filter(groupId=groupId)
- if source:
- userQuery = userQuery.filter(gateway=source)
- userQuery = userQuery.order_by("last_login") if reverse else userQuery.order_by("-last_login")
- if re.match(r'1[3-9][0-9]{9}$', searchKey):
- agent = Agent.objects.filter(id = str(request.user.myBoss.agentId)).first() # type: Agent
- if agent.supports('user_identify'):
- user = MyUser.objects(phoneNumber = searchKey).first()
- if not user:
- return JsonErrorResponse(description = u"未找到用户")
- userQuery = userQuery.filter(openId = user.openId)
- users = list(userQuery.paginate(pageIndex, pageSize))
- else:
- unique_user = UniqueUser.objects.filter(phone = searchKey).first() # type: UniqueUser
- if not unique_user:
- return JsonErrorResponse(description = u"未找到用户")
- userQuery = userQuery.filter(openId = unique_user.openId)
- users = list(userQuery.paginate(pageIndex, pageSize))
- elif re.match(r'^[0-9]{5,10}$', searchKey):
- unique_user = UniqueUser.objects.filter(userId = searchKey).first() # type: UniqueUser
- if not unique_user:
- return JsonErrorResponse(description = u"未找到用户")
- userQuery = userQuery.filter(openId = unique_user.openId)
- users = list(userQuery.paginate(pageIndex, pageSize))
- else:
- userQuery = userQuery.search(searchKey)
- users = list(userQuery.paginate(pageIndex, pageSize))
- # 获取用户默认头像
- openIds = [str(_user.openId) for _user in users]
- openId_2_uniId = {_.openId: _.userId for _ in UniqueUser.objects.filter(openId__in=openIds)}
- dataList = list()
- for _user in users: # type: MyUser
- _userInfo = _user.to_dict()
- _userInfo.update(
- {
- "dealerId": str(request.user.bossId),
- "userId": openId_2_uniId.get(_user.openId, ""),
- "id": str(_user.id)
- }
- )
- dataList.append(_userInfo)
- # 总量永远比数据量大于1 这样前端下拉只需要判断 当前的数量和pageSize的对比就行
- total = pageIndex * pageSize + 1 if len(dataList) == pageSize else pageIndex * pageSize
- return JsonResponse({
- "result": 1,
- "description": None,
- "payload": {"total": total, "dataList": dataList}
- })
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def userDetail(request, openId):
- # 获取所有用户的用户组
- groupIds = Group.get_group_ids_of_dealer(str(request.user.bossId))
- users = MyUser.objects.filter(openId=openId, groupId__in=groupIds).order_by("-last_login")
- user = users.first()
- try:
- userId = UniqueUser.objects.get(openId=user.openId).userId
- except DoesNotExist:
- userId = ""
- # 对于users 做累加和处理以及分列处理
- payload = {
- "userId": userId,
- "avatar": user.avatar or Agent.get_agent(user.agentId).get("productLogo"),
- "openId": openId,
- "nickname": user.nickname,
- "status": "black" if check_black_user(dealerId=str(request.user.bossId), openId=openId) else "white",
- "phone": user.phone,
- "total_recharge": RMB(0),
- "total_balance": VirtualCoin(0),
- "total_consume": VirtualCoin(0),
- }
- dataList = list()
- for _user in users: # type: MyUser
- _groupUserInfo = {
- "groupId": _user.groupId,
- "groupName": Group.get_group(_user.groupId).groupName,
- "recharge": RMB(_user.total_recharged),
- "consume": VirtualCoin(_user.total_consumed),
- "balance": VirtualCoin(_user.balance)
- }
- dataList.append(_groupUserInfo)
- payload["total_recharge"] += _groupUserInfo["recharge"]
- payload["total_consume"] += _groupUserInfo["consume"]
- payload["total_balance"] += _groupUserInfo["balance"]
- payload["dataList"] = dataList
- return JsonOkResponse(payload=payload)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getPortsInfo(request):
- logicalCode = request.GET.get('logicalCode')
- dev = Device.get_dev_by_l(logicalCode)
- smartBox = dev.deviceAdapter
- portList = smartBox.get_ports_info()
- portList = sorted(portList, key=lambda _: int(_['index']))
- if dev.support_power_graph and 'showPG_in_port_detail' in dev.owner.features:
- for item in portList:
- item['showPG'] = True
- return JsonOkResponse(payload={'portList': portList})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getDevicePortDetail(request):
- logicalCode = request.GET.get('logicalCode')
- portIndex = request.GET.get('portIndex')
- dev = Device.get_dev_by_l(logicalCode)
- smartBox = dev.deviceAdapter
- ctrInfo = Device.get_dev_control_cache(dev.devNo)
- payload = smartBox.get_port_using_detail(portIndex, ctrInfo)
- if dev.support_power_graph and 'showPG_in_port_detail' in dev.owner.features:
- payload['showPG'] = True
- payload['index'] = portIndex
- return JsonOkResponse(payload=payload)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取失败"))
- def getDealerSwitch(request, category):
- """
- 两级联动开关 经销商的开关获取
- """
- bossId = str(request.user.bossId)
- try:
- dealer = Dealer.objects.get(id=bossId)
- except DoesNotExist:
- return JsonErrorResponse(u"获取配置失败")
- payload = dealer.get_linkage_switch()
- return JsonOkResponse(payload=payload)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"获取失败"))
- def getGroupSwitch(request, category):
- """
- 两级联动开关 地质组的开关获取
- """
- bossId = str(request.user.bossId)
- pageIndex = int(request.GET.get("pageIndex"))
- pageSize = int(request.GET.get("pageSize"))
- try:
- groups = Group.objects.filter(ownerId=bossId)
- except DoesNotExist:
- return JsonErrorResponse(u"获取配置失败")
- offset = (pageIndex - 1) * pageSize
- total = groups.count()
- dataList = list()
- for _group in groups[offset: offset + pageSize]: # type: Group
- _switches = _group.get_linkage_switch()
- _switches.update({"name": _group.groupName, "groupId": str(_group.id)})
- dataList.append(_switches)
- payload = {
- "total": total,
- "dataList": dataList
- }
- return JsonOkResponse(payload=payload)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败"))
- def setDealerSwitch(request, category):
- """
- 两级联动开关 设置经销商开关
- """
- bossId = str(request.user.bossId)
- try:
- dealer = Dealer.objects.get(id=bossId)
- except DoesNotExist:
- return JsonErrorResponse(u"设置失败")
- payload = json.loads(request.body)
- switch = payload["switch"]
- if switch:
- result = dealer.turn_on(category)
- else:
- result = dealer.turn_off(category)
- return JsonOkResponse() if result else JsonErrorResponse(description=u"设置开关失败,请联系平台客服")
- @permission_required(ROLE.dealer, ROLE.subaccount)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败"))
- def setGroupSwitch(request, category):
- """
- 两级联动开关 设置地质组开关 单个
- """
- bossId = str(request.user.bossId)
- payload = json.loads(request.body)
- groupId = payload["groupId"]
- switch = payload["switch"]
- try:
- group = Group.objects.get(id=groupId, ownerId=bossId)
- except DoesNotExist:
- return JsonErrorResponse(u"设置失败")
- logger.error(group.id)
- if switch:
- group.turn_on(category)
- else:
- group.turn_off(category)
- return JsonOkResponse()
- @permission_required(ROLE.dealer)
- def getServiceChargeModelPara(request):
- """
- 获取服务费模式参数
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- logicalCode = payload.get("logicalCode")
- if isinstance(logicalCode, list) and len(logicalCode):
- logicalCode = logicalCode[0]
- else:
- raise JsonErrorResponse(description=u"无效的设备编号")
- device = Device.get_dev_by_l(logicalCode) # type: DeviceDict
- if device.devTypeCode in [Const.DEVICE_TYPE_CODE_CHANGING_DIANCHUANCARCHARGING]:
- serviceChargeModelPara = device.bill_as_service_feature
- if 'half_hour_price_list' or 'top_price_rate' or 'peak_price_rate' or 'normal_price_rate' or 'valley_price_rate' \
- not in device.bill_as_service_feature['elecCharge']:
- return JsonResponse({"result": 1, "description": "", "payload": device.bill_as_service_feature})
- half_hour_price_list = serviceChargeModelPara['elecCharge']['half_hour_price_list']
- nowTime = datetime.datetime.now().strftime('%H:%M')
- timeNowList = nowTime.split(':')
- index = int(timeNowList[0]) * 2 + 2 if int(timeNowList[1]) > 30 else 1 - 1
- currentElecChargeRate = half_hour_price_list['half_hour_price_list'][index]
- if currentElecChargeRate == 'top_price_rate':
- elecCharge = serviceChargeModelPara['elecCharge']['top_price_rate']
- elif currentElecChargeRate == 'peak_price_rate':
- elecCharge = serviceChargeModelPara['elecCharge']['peak_price_rate']
- elif currentElecChargeRate == 'normal_price_rate':
- elecCharge = serviceChargeModelPara['elecCharge']['normal_price_rate']
- elif currentElecChargeRate == 'valley_price_rate':
- elecCharge = serviceChargeModelPara['elecCharge']['valley_price_rate']
- bill_as_service_feature = {
- 'on':device.bill_as_service_feature['on'],
- 'elecCharge':elecCharge,
- 'serviceCharge':device.bill_as_service_feature['service_charge']
- }
- return JsonResponse({"result": 1, "description": "", "payload": bill_as_service_feature})
- return JsonResponse({"result": 1, "description": "", "payload": device.bill_as_service_feature})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败"))
- def setServiceChargeModelPara(request):
- payload = json.loads(request.body)
- logicalCode = payload.get("logicalCode")
- if isinstance(logicalCode, list) and len(logicalCode):
- logicalCode = logicalCode[0]
- else:
- return JsonErrorResponse(description=u"错误的二维码编号")
- elecCharge = payload.get("elecCharge")
- serviceCharge = payload.get("serviceCharge")
- device = Device.get_dev_by_l(logicalCode)
- devNo = device['devNo']
- # if device.devTypeCode in [Const.DEVICE_TYPE_CODE_CHANGING_DIANCHUANCARCHARGING]:
- # from apps.web.core.adapter.dianchuan_CarCharging import DianchuanCarCharging
- # device = DianchuanCarCharging(device)
- # device.set_elec_charge_by_dealer(elecCharge)
- # elecChargeDict = {
- # 'top_price_rate' : elecCharge,
- # 'peak_price_rate' : elecCharge,
- # 'normal_price_rate' : elecCharge,
- # 'valley_price_rate' : elecCharge,
- # 'half_hour_price_list' : ['top_price_rate'] * 48,
- # }
- # Device.get_collection().update_one({'devNo': devNo}, {
- # '$set': {
- # 'devType.features.billAsService.elecCharge': elecChargeDict,
- # 'devType.features.billAsService.serviceCharge': serviceCharge
- # }
- # })
- # Device.invalid_device_cache(devNo)
- # return JsonOkResponse()
- Device.get_collection().update_one({'devNo': devNo}, {
- '$set': {
- 'devType.features.billAsService.elecCharge': elecCharge,
- 'devType.features.billAsService.serviceCharge': serviceCharge
- }
- })
- Device.invalid_device_cache(devNo)
- return JsonOkResponse()
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getApiInfo(request):
- """
- 获取首页的配额相关数据
- """
- dealer = request.user.myBoss # type: Dealer
- payload = dealer.api_quota_info
- return JsonOkResponse(payload=payload)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getApiAppInfo(request):
- """
- 获取经销上API注册信息
- """
- dealer = request.user.myBoss # type: Dealer
- apiAppInfo = dealer.api_app # type: ApiAppInfo
- return JsonOkResponse(payload={
- 'people': apiAppInfo.people,
- 'tel': apiAppInfo.tel,
- 'callbackUrl': apiAppInfo.callbackUrl,
- 'apiDeviceMax': apiAppInfo.apiDeviceMax
- })
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def saveApiAppInfo(request):
- """
- 编辑经销上API注册信息
- """
- def check_url(url):
- return re.match(r'^((https|http|ftp|rtsp|mms)?:\/\/)[^\s]+', url)
- dealer = request.user.myBoss # type: Dealer
- payload = json.loads(request.body)
- people = payload.get('people')
- tel = payload.get('tel')
- callbackUrl = payload.get('callbackUrl')
- if callbackUrl and not check_url(callbackUrl):
- return JsonErrorResponse(description='回调地址Url填写错误')
- dealer.update_api_app(**{
- 'people': people,
- 'tel': tel,
- 'callbackUrl': callbackUrl
- })
- return JsonOkResponse()
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getApiDevice(request):
- """
- 获取经销商的设备列表
- """
- dealerId = request.user.bossId # type: Dealer
- groups = Group.get_group_ids_of_dealer(dealerId)
- groupList = []
- for groupId in groups:
- group = Group.get_group(groupId) # type : GroupDict
- devDict = Device.get_devices_by_group([groupId]) # type:Mapping[DeviceDict]
- if devDict:
- devs = devDict.values()
- groupList.append({
- 'groupName': group['groupName'],
- 'devList': map(lambda _: {'title': '{}_{}'.format(_.devTypeName, _.logicalCode), 'isApi': _.isApi,
- 'logicalCode': _.logicalCode}, devs)
- })
- return JsonOkResponse(payload={'groupList': groupList})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def editApiDevice(request):
- """
- 经销商选择api设备
- """
- dealer = request.user.myBoss # type: Dealer
- payload = json.loads(request.body)
- groupList = payload.get('groupList')
- logicalCodes = []
- for item in groupList:
- logicalCodes += item['devList']
- # 找出经销商的全部设备
- groups = Group.get_group_ids_of_dealer(str(dealer.id))
- devDict = Device.get_devices_by_group(groups)
- allList = map(lambda _: _.logicalCode, devDict.values())
- # 找出经销商操作的设备
- trunOnList = map(lambda _: _['logicalCode'], filter(lambda _: _['isApi'] == True, logicalCodes))
- trunOnCount = len(trunOnList)
- if set(trunOnList) - set(allList):
- return JsonErrorResponse(description='非法操作!!! 无法操作其他人的设备')
- apiInfo = dealer.api_app # type: ApiAppInfo
- apiDeviceMax = apiInfo.apiDeviceMax
- if trunOnCount > apiDeviceMax:
- return JsonResponse({'result': 1001, 'description': '经销商API设备配额不足,请购买API设备配额',
- 'payload': {'needQuota': trunOnCount - apiDeviceMax}})
- # 此编辑操作为 关闭此经销商的全部设备 然后开启经销商选中的
- Device.switch_api_mode(allList, isApi=False)
- Device.switch_api_mode(trunOnList, isApi=True)
- return JsonOkResponse()
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def createQuotaOrder(request):
- dealer = request.user.myBoss # type: Dealer
- payload = json.loads(request.body)
- needQuota = payload.get('needQuota')
- groupList = payload.get('groupList')
- buyType = payload.get('buyType')
- package = payload.get('package', {})
- logicalCodes = []
- if buyType == 'temporary': # 配置设备的时候临时购买
- for item in groupList:
- logicalCodes += item['devList']
- # 找出经销商的全部设备
- groups = Group.get_group_ids_of_dealer(str(dealer.id))
- devDict = Device.get_devices_by_group(groups)
- # 找出经销商操作的设备
- trunOnList = map(lambda _: _['logicalCode'], filter(lambda _: _['isApi'] == True, logicalCodes))
- trunOnCount = len(trunOnList)
- if set(trunOnList) - set(map(lambda _: _.logicalCode, devDict.values())):
- return JsonErrorResponse(description='非法操作!!! 无法操作其他人的设备')
- apiInfo = dealer.api_app # type: ApiAppInfo
- apiDeviceMax = apiInfo.apiDeviceMax
- if trunOnCount - apiDeviceMax <= 0:
- return JsonErrorResponse(description='参数传入有误, 请稍后重试!')
- if trunOnCount - apiDeviceMax != int(needQuota):
- return JsonErrorResponse(description='参数传入有误, 请稍后重试..')
- payload = {
- 'needQuota': needQuota,
- 'trunOnList': trunOnList,
- 'buyType': buyType
- }
- elif buyType == 'package': # 套餐购买页面过来
- payload = {
- 'needQuota': package.get('quota', 1),
- 'trunOnList': [],
- 'buyType': buyType,
- 'package': package
- }
- else:
- return JsonErrorResponse(description='参数传入错误, 请稍后从试')
- # 创建订单
- record = create_dealer_charge_order_for_api(dealer, **payload)
- if record:
- return JsonResponse({'result': 1, 'description': u'创建订单成功', 'payload':{'orderNo':record.orderNo}})
- else:
- return JsonErrorResponse(u'创建订单异常失败')
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getQuotaDiscountPackage(request):
- dealer = request.user.myBoss # type: Dealer
- apiInfo = dealer.api_app # type: ApiAppInfo
- unitPrice = apiInfo.apiDevicePerCost
- payload = {
- "unitPrice": unitPrice,
- "discountList": [
- {
- "id": 1,
- "price": unitPrice * 10,
- "quota": 10
- },
- {
- "id": 2,
- "price": unitPrice * 20,
- "quota": 20
- },
- {
- "id": 3,
- "price": unitPrice * 40,
- "quota": 40
- },
- {
- "id": 4,
- "price": unitPrice * 100,
- "quota": 100
- }
- ]
- }
- return JsonOkResponse(payload=payload)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getDisableAdInfo(request):
- """
- 获取首页的配额相关数据
- """
- dealer = request.user.myBoss # type: Dealer
- payload = dealer.disable_ad_quota_info()
- return JsonOkResponse(payload=payload)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getDisableAdDevice(request):
- dealerId = request.user.bossId # type: Dealer
- groups = Group.get_group_ids_of_dealer(dealerId)
- groupList = []
- now = datetime.datetime.now()
- def _filter(dev):
- formart_dict = {
- 'title': '{}_{}'.format(dev.devTypeName, dev.logicalCode),
- 'logicalCode': dev.logicalCode,
- 'expiredTime':None
- }
- if dev.disableADExpireDate and dev.disableADExpireDate > now:
- formart_dict.update({
- 'expiredTime': dev.disableADExpireDate.strftime("%Y-%m-%d %H:%M:%S")
- })
- return formart_dict
- for groupId in groups:
- group = Group.get_group(groupId) # type : GroupDict
- devDict = Device.get_devices_by_group([groupId]) # type:Mapping[DeviceDict]
- if devDict:
- devs = devDict.values()
- groupList.append({
- 'groupName': group['groupName'],
- 'devList': map(_filter, devs)
- })
- return JsonOkResponse(payload={'groupList': groupList})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def DisableAdDeviceRecharge(request):
- payload = json.loads(request.body)
- groupList = payload.get('groupList', [])
- devList = []
- for item in groupList:
- devList += item.get('devList', [])
- configuredList = filter(lambda _: _['configured'] == True, devList)
- payInfo = []
- total = 0
- totalMoney = RMB(0)
- for item in configuredList:
- dev = Device.get_dev_by_l(item.get('logicalCode'))
- if not dev:
- continue
- payInfo.append({
- 'title': item.get('title'),
- 'logicalCode':dev.logicalCode,
- 'expireDate': dev.disableADExpireDate,
- 'money': dev.owner.disable_ad_plan.disableAdCost.mongo_amount,
- 'cycle': dev.owner.disable_ad_plan.cycle
- })
- total += 1
- totalMoney += dev.owner.disable_ad_plan.disableAdCost
- return JsonOkResponse(payload={'devList': payInfo, 'total':total, 'totalMoney':totalMoney.mongo_amount})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u"设置失败"))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def createDisableAdOrder(request):
- dealer = request.user.myBoss # type: Dealer
- payload = json.loads(request.body)
- buyType = payload.get('buyType')
- devList = payload.get('devList', {})
- logicalCodes = []
- if buyType != 'temporary': # 配置设备的时候临时购买
- return JsonErrorResponse(description='参数传入错误, 请稍后从试')
- for item in devList:
- logicalCodes.append(item['logicalCode'])
- # 找出经销商的全部设备
- devs = Device.get_devs_by_ownerId(str(dealer.id))
- # 找出经销商将要操作的设备
- if set(logicalCodes) - set(map(lambda _: _.logicalCode, devs)):
- return JsonErrorResponse(description='非法操作!!! 无法操作其他人的设备')
- # 创建订单
- record = create_dealer_charge_order_for_disable_ad(dealer, devList)
- if record:
- return JsonResponse({'result': 1, 'description': u'创建订单成功', 'payload':{'orderNo':record.orderNo}})
- else:
- return JsonErrorResponse(u'创建订单异常失败')
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getServerFunction(request):
- payload = json.loads(request.body)
- lc = payload.get("logicalCode")
- if isinstance(lc, list) and len(lc):
- lc = lc[0]
- else:
- raise JsonErrorResponse(description=u"无效的设备编号")
- dev = Device.get_dev_by_l(lc) # type: DeviceDict
- if not dev:
- return JsonResponse({'result': 0, 'description': u'未找到该设备', 'payload': {}})
- setConf = dev.deviceAdapter.get_server_setting()
- if setConf is None:
- return JsonResponse({'result': 0, 'description': u'您的设备类型不支持此操作哦', 'payload': {}})
- else:
- return JsonResponse({'result': 1, 'description': u'', 'payload': setConf})
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def setServerFunction(request):
- payload = json.loads(request.body)
- # 去掉多余的参数
- payload.pop('groupId', None)
- logicalCodes = payload.pop('logicalCode')
- if len(logicalCodes) > 1:
- dev = Device.get_dev_by_l(logicalCodes[0]) # type: DeviceDict
- payload = {
- 'operator': {
- 'id': str(request.user.id),
- 'role': request.user.role,
- 'username': request.user.username
- },
- 'logicalCodes': logicalCodes,
- 'payload': payload,
- 'ownerId': dev.ownerId,
- 'devTypeCode': dev.devTypeCode,
- 'operationId': 'server_setting_{}_{}'.format(str(request.user.id), int(time.time()))
- }
- from taskmanager.mediator import task_caller
- task_caller('batch_set_server_settings', **payload)
- return JsonResponse({'result': 1, 'description': None, 'payload': {'operationId': payload['operationId']}})
- else:
- device = Device.get_dev_by_l(logicalCodes[0]) # type: DeviceDict
- if not device:
- return JsonResponse({'result': 0, 'description': u'没有找到设备', 'payload': {}})
- if device.ownerId != str(request.user.bossId):
- return JsonResponse({'result': 0, 'description': u'非法操作', 'payload': {}})
- try:
- before = device.deviceAdapter.get_server_setting()
- device.deviceAdapter.set_server_setting(payload)
- OperatorLog.log_dev_operation(
- operator=request.user,
- device=device,
- operator_name='setServerSetting',
- content={
- 'before': before, 'after': payload
- })
- except InvalidParameter as e:
- return JsonErrorResponse(description=e.message)
- return JsonOkResponse()
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getDealerPreferentialRechargeTemplate(request):
- ownerId = str(request.user.bossId)
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- templateType = str(request.GET.get('type'))
- dealer = Dealer.objects(id=ownerId).first()
- if dealer is None:
- return JsonErrorResponse(description=u'未知错误')
- if templateType == 'preferentialRechargeTemplate':
- dataList = dealer.templateSet.rechargeDiscount
- elif templateType == 'cardPreferentialRechargeTemplate':
- dataList = dealer.templateSet.cardRechargeDiscount
- else:
- return JsonErrorResponse(description=u"未知错误")
- payload = {
- "total": len(dataList),
- "dataList": dataList[(pageIndex - 1) * pageSize:pageIndex * pageSize]
- }
- return JsonOkResponse(payload=payload)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getDealerPreferentialRechargeTemplateById(request):
- ownerId = str(request.user.bossId)
- templateId = request.GET.get('id', None)
- templateType = str(request.GET.get('type'))
- if templateId is None:
- return JsonErrorResponse(description=u'未知错误')
- dealer = Dealer.objects(id=ownerId).first()
- if dealer is None:
- return JsonErrorResponse(description=u'未知错误')
- if templateType == 'preferentialRechargeTemplate':
- dataList = dealer.templateSet.rechargeDiscount
- elif templateType == 'cardPreferentialRechargeTemplate':
- dataList = dealer.templateSet.cardRechargeDiscount
- else:
- return JsonErrorResponse(description=u"未知错误")
- payload = [_ for _ in dataList if int(templateId) == int(_['id'])][0]
- return JsonOkResponse(payload=payload)
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def editDealerPreferentialRechargeTemplate(request):
- ownerId = str(request.user.bossId)
- tempData = json.loads(request.body)
- templateType = tempData['type']
- del tempData['type']
- dealer = Dealer.objects(id=ownerId).first()
- if dealer is None:
- return JsonErrorResponse(description=u'未知错误')
- if templateType == 'preferentialRechargeTemplate':
- tempDataList = dealer.templateSet.rechargeDiscount
- elif templateType == 'cardPreferentialRechargeTemplate':
- tempDataList = dealer.templateSet.cardRechargeDiscount
- else:
- return JsonErrorResponse(description=u"未知错误")
- for _ in tempDataList:
- if int(_['id']) == int(tempData['id']):
- tempDataList.remove(_)
- tempDataList.append(tempData)
- if templateType == 'preferentialRechargeTemplate':
- dealer.templateSet.rechargeDiscount = tempDataList
- else:
- dealer.templateSet.cardRechargeDiscount = tempDataList
- dealer.save()
- return JsonOkResponse()
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def addDealerPreferentialRechargeTemplate(request):
- ownerId = str(request.user.bossId)
- payload = json.loads(request.body)
- templateType = payload['type']
- dealer = Dealer.objects(id=ownerId).first()
- if dealer is None:
- return JsonErrorResponse(description=u'未知错误')
- if templateType == 'preferentialRechargeTemplate':
- tempDataList = dealer.templateSet.rechargeDiscount
- elif templateType == 'cardPreferentialRechargeTemplate':
- tempDataList = dealer.templateSet.cardRechargeDiscount
- else:
- return JsonErrorResponse(description=u"未知错误")
- if len(tempDataList) == 0:
- tempId = 1
- else:
- tempId = max(int(_['id']) for _ in tempDataList) + 1
- temp = {}
- templateInfo = payload.get('templateInfo', [])
- templateName = payload.get('templateName', '')
- if not templateInfo or templateName == '':
- return JsonErrorResponse(description=u'套餐错误')
- for _ in templateInfo:
- _['coins'] = float(_['coins'])
- _['ruleId'] = _['payAmount']
- temp.update({'templateName': templateName, 'templateInfo': templateInfo, 'id': tempId})
- if templateType == 'preferentialRechargeTemplate':
- dealer.templateSet.rechargeDiscount.append(temp)
- else:
- dealer.templateSet.cardRechargeDiscount.append(temp)
- dealer.save()
- return JsonOkResponse()
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def deleteDealerPreferentialRechargeTemplate(request):
- ownerId = str(request.user.bossId)
- payload = json.loads(request.body)
- tempId = payload['id']
- templateType = payload['type']
- dealer = Dealer.objects(id=ownerId).first()
- if dealer is None:
- return JsonErrorResponse(description=u'未知错误')
- if templateType == 'preferentialRechargeTemplate':
- tempDataList = dealer.templateSet.rechargeDiscount
- elif templateType == 'cardPreferentialRechargeTemplate':
- tempDataList = dealer.templateSet.cardRechargeDiscount
- else:
- return JsonErrorResponse(description=u"未知错误")
- for _ in tempDataList:
- if int(_['id']) == int(tempId):
- tempDataList.remove(_)
- if templateType == 'preferentialRechargeTemplate':
- dealer.templateSet.rechargeDiscount = tempDataList
- else:
- dealer.templateSet.cardRechargeDiscount = tempDataList
- dealer.save()
- return JsonOkResponse()
- @error_tolerate(logger=logger, nil=JsonErrorResponse(u'未知错误'))
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def editGroupsToPreferentialRechargeTemplate(request):
- ownerId = str(request.user.bossId)
- payload = json.loads(request.body)
- tempId = payload['id']
- templateType = payload['type']
- groupIds = [_['groupId'] for _ in payload['groupId']]
- dealer = Dealer.objects(id=ownerId).first()
- if dealer is None:
- return JsonErrorResponse(description=u'未知错误')
- tempData = dict()
- if templateType == 'preferentialRechargeTemplate':
- tempDataList = dealer.templateSet.rechargeDiscount
- elif templateType == 'cardPreferentialRechargeTemplate':
- tempDataList = dealer.templateSet.cardRechargeDiscount
- else:
- return JsonErrorResponse(description=u"未知错误")
- for _ in tempDataList:
- if int(_['id']) == int(tempId):
- tempData = _
- break
- tempRule = dict()
- for _ in tempData['templateInfo']:
- tempRule.update({_['payAmount']: _['coins']})
- if templateType == 'preferentialRechargeTemplate':
- for _ in Group.objects(id__in=groupIds):
- _.ruleDict = format_dot_key(tempRule)
- _.save()
- else:
- for _ in Group.objects(id__in=groupIds):
- _.cardRuleDict = format_dot_key(tempRule)
- _.save()
- GroupCacheMgr.invalid_group_cache(groupIds)
- return JsonOkResponse()
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getServiceFeePackage(request):
- logicalCode = request.GET.get('logicalCode')
- if not logicalCode:
- raise JsonErrorResponse(description=u'无效的设备编号')
- dev = Device.get_dev_by_l(logicalCode) # type: DeviceDict
- payload = dev.deviceAdapter.get_service_fee_info()
- return JsonResponse({'result': 1, 'description': '', 'payload': payload})
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def setServiceFeePackage(request):
- """
- 设置服务费计费参数, 暂时不支持批量
- :param request:
- :return:
- """
- payload = json.loads(request.body)
- if 'billAsService' not in payload:
- return JsonErrorResponse(description=u'传入参数错误')
- logicalCode = payload.get("logicalCode")
- try:
- device = Device.get_dev_by_l(logicalCode) # type: DeviceDict
- device.deviceAdapter.set_service_fee_info(payload)
- except InvalidParameter as e:
- return JsonErrorResponse(description=e.message)
- return JsonOkResponse()
- @permission_required(ROLE.dealer)
- def interconnectionConfig(request):
- ownerId = str(request.user.bossId)
- pageIndex = int(request.GET.get('pageIndex', 1))
- pageSize = int(request.GET.get('pageSize', 10))
- searchKey = str(request.GET.get('searchKey', ''))
-
- swapFlagSearch = None
- if 'swapFlag' in request.GET:
- if request.GET.get('swapFlag') == 'false':
- swapFlagSearch = False
- else:
- swapFlagSearch = True
- dataList = []
- groupIds = Group.get_group_ids_of_dealer(ownerId)
- groupList = Group.get_groups_by_group_ids(groupIds).values()
- groupList = natural_sort(groupList, 'groupName', False)
- for grp in groupList:
- if searchKey not in grp['groupName']:
- continue
-
- if swapFlagSearch is not None and swapFlagSearch != grp.get('swapFlag', False):
- continue
-
- if 'swapFlag' not in grp:
- grp['swapFlag'] = False
- elif grp['swapFlag']:
- swapInfo = SwapGroup.objects(groupId=grp['groupId']).first()
- if swapInfo is not None:
- grp['joinedTime'] = swapInfo.joinedTime.strftime('%Y-%m-%d %H:%M:%S')
-
- dataList.append(grp)
- return JsonResponse({
- "result": 1,
- "description": None,
- 'payload': {
- "total": len(dataList),
- "dataList": dataList[(pageIndex - 1) * pageSize: pageIndex * pageSize]
- }
- })
- @permission_required(ROLE.dealer)
- def interconnectionDetail(request):
- ownerId = str(request.user.bossId)
- groupId = request.GET.get('groupId', None)
- if groupId is None:
- return JsonErrorResponse(description=u"缺少参数")
-
- swapInfo = SwapGroup.objects(groupId=groupId).first()
-
- if swapInfo is None:
- return JsonOkResponse(payload={})
-
- if ownerId != swapInfo.ownerId:
- return JsonErrorResponse(description=u"参数不一致")
-
-
- payload = {
- 'StationLng':swapInfo.lng,
- 'StationLat':swapInfo.lat,
- 'BusineHours':swapInfo.BusineHours,
- 'SiteGuide':swapInfo.SiteGuide,
- 'Construction':swapInfo.Construction,
- 'SupportOrder':swapInfo.SupportOrder,
- 'Pictures':[{'PicID':pic.PicID, 'IsCover':pic.IsCover, 'Url':pic.Url, 'title':pic.Title, 'Title':pic.TitleForShow} for pic in swapInfo.Pictures],
- 'MatchCars':swapInfo.MatchCars,
- 'ParkInfo':swapInfo.ParkInfo,
- 'StationStatus':swapInfo.StationStatus,
- 'ParkNums':swapInfo.ParkNums,
- 'originalAlternateFeeRemark':swapInfo.originalAlternateFeeRemark,
- 'alternateFeeRemark':swapInfo.alternateFeeRemark,
- 'originalDirectFeeRemark':swapInfo.originalDirectFeeRemark,
- 'directFeeRemark':swapInfo.directFeeRemark,
- 'PriceChargingInfo':[{'FeeTime':info.FeeTime, 'ElectricityFee':info.ElectricityFee, 'ServiceFee':info.ServiceFee} for info in swapInfo.PriceChargingInfo],
- 'DiscountPriceChargingInfo':[{'FeeTime':info.DiscountTime, 'ElectricityFee':info.DiscountElectricityFee, 'ServiceFee':info.DiscountServiceFee} for info in swapInfo.DiscountPriceChargingInfo],
- 'ElectricityFee':swapInfo.ElectricityFee,
- 'ServiceFee':swapInfo.ServiceFee,
- 'ParkFee':swapInfo.ParkFee,
- 'chargeTagList':[{'tagId':tag.tagId, 'tagType':tag.tagType, 'tagDesc':tag.tagDesc, 'tagOrder':tag.tagOrder, 'tagName':tag.tagName, 'color':tag.color} for tag in swapInfo.ChargeTagList],
- 'StationTel':swapInfo.StationTel,
- 'ServiceTel':swapInfo.ServiceTel,
- 'Payment':swapInfo.Payment,
- 'Remark':swapInfo.Remark,
- 'RightTag':swapInfo.RightTag,
- 'StationType':swapInfo.StationType
- }
-
- if swapInfo.swapFlag:
- payload.update({'joinedTime':swapInfo.joinedTime.strftime('%Y-%m-%d %H:%M:%S')})
-
- return JsonOkResponse(payload=payload)
- @permission_required(ROLE.dealer)
- def uploadSwapPicture(request):
- files = request.FILES.getlist('file')
- groupId = request.POST.get('groupId', None)
- tail = request.POST.get('tail', None)
-
- if groupId is None:
- return JsonErrorResponse(description=u"缺少参数")
-
- if not len(files):
- return JsonResponse({'result': 0, 'description': u'未找到上传的商品图片,请重新试试', 'payload': {}})
- uploader = SwapGroupPicFileUploader(inputFile=request.FILES.getlist('file')[0], uploadType='swap', groupId=groupId, tail=tail)
- logger.info('[uploadItemPic] %s is being used' % (repr(uploader),))
- try:
- outputUrl = uploader.upload()
- return JsonResponse({'result': 1, 'description': '', 'payload': {'Url':outputUrl}})
- except InvalidFileSize, e:
- logger.info(
- '%s(id=%s)\'s uploaded file reached limit' % (request.user.__class__.__name__, str(request.user.id),))
- return JsonResponse({'result': 0, 'description': e.message, 'payload': {}})
- except InvalidFileName, e:
- logger.info(
- '%s(id=%s)\'s uploaded file name is not legal' % (request.user.__class__.__name__, str(request.user.id),))
-
- return JsonResponse({'result': 0, 'description': e.message, 'payload': {}})
-
- @permission_required(ROLE.dealer)
- def getFeeMode(request):
- payload = request.POST
- logicalCode = payload.get("logicalCode")
- devObj = Device.objects.get(logicalCode=logicalCode)
- if devObj.ownerId != str(request.user.id):
- return JsonErrorResponse(description=u"参数错误")
-
- feeMode = devObj.otherConf.get('feeMode', {})
- timeRateList = []
- shiduan = feeMode.get('shiduan', '000000000000000000000000000000000000000000000000')
-
- for ii in range(48):
- startHour = 0 + ii / 2
- startMin = '00' if ii % 2 == 0 else '30'
- endHour = startHour if ii % 2 == 0 else startHour + 1
- endMin = '30' if ii % 2 == 0 else '00'
- startTime = '%02d:%s' % (startHour, startMin)
- endTime = '%02d:%s' % (endHour, endMin)
- timeRateList.append({'startTime':startTime, 'endTime':endTime, 'rate':shiduan[ii]})
-
- result = {'top_price_rate':feeMode.get('jianFee', 0),
- 'top_price_service_rate':feeMode.get('jianServe', 0),
- 'peak_price_rate':feeMode.get('fengFee', 0),
- 'peak_price_service_rate':feeMode.get('fengServe', 0),
- 'normal_price_rate':feeMode.get('pingFee', 0),
- 'normal_price_service_rate':feeMode.get('pingServe', 0),
- 'valley_price_rate':feeMode.get('guFee', 0),
- 'valley_price_service_rate':feeMode.get('guServe', 0),
- 'jishunScale':feeMode.get('jishunScale', 0),
- 'timeRateList':timeRateList}
-
- return result
- @permission_required(ROLE.dealer)
- def setFeeMode(request):
- payload = request.POST
- logicalCode = payload.get("logicalCode")
- devObj = Device.objects.get(logicalCode=logicalCode)
- if devObj.ownerId != str(request.user.id):
- return JsonErrorResponse(description=u"参数错误")
-
- feeMode = devObj.otherConf.get('feeMode', {})
- feeMode['jianFee'] = float(request.POST.get('top_price_rate'))
- feeMode['jianServe'] = float(request.POST.get('top_price_service_rate'))
- feeMode['fengFee'] = float(request.POST.get('peak_price_rate'))
- feeMode['fengServe'] = float(request.POST.get('peak_price_service_rate'))
- feeMode['pingFee'] = float(request.POST.get('normal_price_rate'))
- feeMode['pingServe'] = float(request.POST.get('normal_price_service_rate'))
- feeMode['guFee'] = float(request.POST.get('valley_price_rate'))
- feeMode['guServe'] = float(request.POST.get('valley_price_service_rate'))
- feeMode['jishunScale'] = float(request.POST.get('jishunScale', 0))
-
- shiduan = ''
- for ii in range(48):
- startHour = 0 + ii / 2
- startMin = '00' if ii % 2 == 0 else '30'
- endHour = startHour if ii % 2 == 0 else startHour + 1
- endMin = '30' if ii % 2 == 0 else '00'
- startTime = '%02d:%s' % (startHour, startMin)
- endTime = '%02d:%s' % (endHour, endMin)
- print startTime, endTime
- harfHourValue = '0'
- for conf in request.POST.get('timeRateList'):
- if startTime >= conf['startTime'] and endTime <= conf['endTime']:
- harfHourValue = conf['rate']
- break
- else:
- continue
- shiduan += harfHourValue
-
- feeMode['shiduan'] = shiduan
-
- try:
- devObj.save()
- except Exception, e:
- return JsonResponse({"result": 2, "description": "配置失败,请重试"})
-
- return JsonOkResponse()
- @permission_required(ROLE.dealer)
- def setGroupSwapFlag(request):
- ownerId = str(request.user.bossId)
- groupId = request.POST.get('groupId', None)
- if groupId is None:
- return JsonErrorResponse(description=u"缺少参数")
- swapFalg = request.POST.get('swapFlag', False)
- success, description, groupId = Group.update_group(groupId, swapFalg=swapFalg)
- SwapGroup.get_collection().update({'groupId':groupId}, {'$set':{'swapFlag':swapFalg}})
- return JsonOkResponse() if success else JsonErrorResponse(description=description,
- payload={'groupId': groupId})
- @permission_required(ROLE.dealer)
- def saveInterconnectionDetail(request):
- ownerId = str(request.user.bossId)
- data = json.loads(request.body)
- groupId = data.get('groupId', None)
- if groupId is None:
- return JsonErrorResponse(description=u"缺少参数")
- group = Group.get_group(groupId)
- if group is None:
- return JsonErrorResponse(description=u"参数错误")
-
- swapInfo = SwapGroup.objects(groupId=groupId).first()
- if swapInfo is None:
- swapInfo = SwapGroup(groupId=groupId, stationID=SwapGroup.make_stationID(groupId))
-
- lng, lat = SwapGroup.bd09_to_gcj02(data['StationLng'], data['StationLat'])
- swapInfo.ownerId = ownerId
- swapInfo.swapFlag = data.get('swapFlag', False)
- swapInfo.location = {'type':'Point', 'coordinates':[data['StationLng'], data['StationLat']]}
- swapInfo.gcjLng = lng
- swapInfo.gcjLat = lat
- swapInfo.BusineHours = data['BusineHours']
- swapInfo.SiteGuide = data['SiteGuide']
- swapInfo.Construction = data['Construction']
- swapInfo.SupportOrder = int(data['SupportOrder'])
- ii = 0
- picList = []
- for pic in data['Pictures']:
- ii += 1
- picList.append(Picture(ii, pic['IsCover'], pic['Url'], pic['title'], pic['Title']))
-
- swapInfo.Pictures = picList
- swapInfo.MatchCars = data['MatchCars']
- swapInfo.ParkInfo = data['ParkInfo']
- swapInfo.StationStatus = data['StationStatus']
- swapInfo.ParkNums = data['ParkNums']
- swapInfo.originalAlternateFeeRemark = data['originalAlternateFeeRemark']
- swapInfo.alternateFeeRemark = data['alternateFeeRemark']
- swapInfo.originalDirectFeeRemark = data['originalDirectFeeRemark']
- swapInfo.directFeeRemark = data['directFeeRemark']
- swapInfo.PriceChargingInfo = [PriceCharging(info['FeeTime'], info['ElectricityFee'], info['ServiceFee']) for info in data['PriceChargingInfo']]
- swapInfo.DiscountPriceChargingInfo = [DiscountPriceCharging(info['FeeTime'], info['ElectricityFee'], info['ServiceFee']) for info in data['DiscountPriceChargingInfo']]
- swapInfo.ElectricityFee = data['ElectricityFee']
- swapInfo.ServiceFee = data['ServiceFee']
- swapInfo.ParkFee = data['ParkFee']
- swapInfo.ChargeTagList = [ChargeTag(0, tag['tagType'], tag['tagDesc'], tag['tagOrder'], tag['tagName'], tag['color']) for tag in data.get('chargeTagList', [])]
- swapInfo.StationTel = data['StationTel']
- swapInfo.ServiceTel = data['ServiceTel']
- swapInfo.Payment = data['Payment']
- swapInfo.SupportOrder = data['SupportOrder']
- swapInfo.Remark = data['Remark']
- swapInfo.RightTag = data['RightTag']
- swapInfo.StationType = data['StationType']
-
- if swapInfo.swapFlag:
- swapInfo.joinedTime = datetime.datetime.now()
-
- try:
- swapInfo.save()
- except Exception, e:
- return JsonResponse({"result": 2, "description": "配置失败,请重试"})
-
- Group.update_group(group_id=groupId, swapFlag=swapInfo.swapFlag)
-
- SwapGroup.recount_devnum(groupId)
-
- return JsonOkResponse()
- @permission_required(ROLE.dealer)
- def getInterconnectionDisclaimer(request):
- payload = {
- 'version': '1.01',
- 'content': '<p style="text-align:center;"> 互联互通用户协议</p><p style="text-align:left;"> <br />一、【首部及导言】<br />欢迎您使用充电桩互联互通协议!<br />本系统互联互通协议遵从国家关于充电桩互联互通的协议《T/CEC中国电力企业联合会标准》,关于协议的具体规则,可以联系我们技术支持。<br />二、【协议的范围】<br />1、本协议是您与我们充电桩管理平台(以下简称我们)之间关于您使用互联互通功能服务所订立的协议。</p><p style="text-align:left;"> 2、本协议的用户,只指通过我们充电桩管理平台,管理设备的运营商组织和个人,都属于我们的用户。</p><p style="text-align:left;"> 三、【服务内容】<br /><span>1、本协议服务的设备,只有当您打开互联互通开关后,设备才会加入互联互通。关闭开关后,将会地址地址组下的互联互通功能。</span></p>\
- <p style="text-align:left;"> 2、<span>互联互通主要是通过第三方的APP、小程序、H5应用,能够查询到您旗下的设备,并能够通过第三方能够启动充电,并根据账单进行结算。</span></p><p style="text-align:left;">\
- <span>3、互联互通的第三方APP,包括不限于诸如:快电、小桔充电、恒大星脉等等第三方平台,而且每个第三方平台会存在不同的服务区别,包括通过第三方使用充电桩需要提取的佣金、费用结算方式、营销活动推广费用、提现费率等等,具体\
- 情况,在互联互通开放时,请您和我们技术支持沟通确认。</span></p><p style="text-align:left;"> <span>四、【服务要求】</span></p><p style="text-align:left;"> <span>1、您提供的设备,包括交流桩和直流桩,能够保证设备的安全性、可靠性、可用性,以及设备本身的数据统计准确,应当尽量避免因此引起的纠纷。因此而引起的纠纷,我们要求由您负责并处理。</span>\
- </p><p style="text-align:left;"> <span>2、您提供配置的设备信息,包括互联互通的信息,应当准确并符合实际,避免出现消费者对平台进行投诉,因此产生的投诉,将有您负责,并且我们将有权对不符合实际情况的互联互通进行关闭,以保障充电用户的权益。</span>\
- </p><p style="text-align:left;"> <span>3、产生的一些售后处理,可能需要您和我们一起处理,我们希望您保持联系方式的畅通,以保证服务质量。如果用户或者第三方平台投诉到我们这里,我们却多次无法联系到您,我们有权强制禁用您的互联互通功能。</span></p>\
- <p style="text-align:left;"> <span>五、【售后及其他】</span></p><p style="text-align:left;"> <span>1、平台的相关售后,包括您使用的后台、互联互通,由我们负责,如有疑问,可以直接联系我们。</span>\
- </p><p style="text-align:left;"> <span>2、设备相关售后,诸如设备故障、设备维修等,导致的互联互通服务售后,由您负责,我们售后可能会联系您,需要您保持联系方式畅通。</span></p><p style="text-align:left;"> <span><br /></span></p>'
- }
- return JsonOkResponse(payload=payload)
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def getCustomizePoint(request):
- logicalCode = request.GET.get('logicalCode')
- dev = Device.get_dev_by_l(logicalCode)
- if dev is None:
- return JsonErrorResponse(description=u"参数错误")
-
- box = ActionDeviceBuilder.create_action_device(dev)
- unit = box.get_customize_score_unit()
- if unit is None:
- return JsonResponse({'result': 0, 'description': "", 'payload': {}})
- return JsonResponse({'result': 0, 'description': "", 'payload': [unit]})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer, ROLE.subaccount)
- def onCustomizePoint(request):
- logicalCode = request.POST.get('logicalCode')
- pointNum = request.POST.get('time')
- portList = json.loads(request.POST.get('attachParas')).get('chargeIndex')
- openId = request.user.managerialOpenId
- dev = Device.get_dev_by_l(logicalCode)
- if dev is None:
- return JsonErrorResponse(description=u"参数错误")
-
- box = ActionDeviceBuilder.create_action_device(dev)
- address = Group.get_group(dev['groupId'])['address']
- groupName = Group.get_group(dev['groupId'])['groupName']
-
- errorList = []
- errdesc = ''
- for port in portList:
- try:
- box.start_customize_point(pointNum, openId, int(port))
- UpscoreRecord(
- logicalCode=dev['logicalCode'],
- devNo=dev['devNo'],
- ownerId=str(request.user.id),
- time=datetime.datetime.now(),
- score=pointNum,
- address=address,
- groupName=groupName,
- devType=dev['devType']['name'],
- type="",
- remark=u'自定义上分:%s%s' % (pointNum, request.POST.get('unit'))
- ).save()
- except ServiceException, e:
- errorList.append(port)
- errdesc = ',' + e.result.get('description')
- continue
- except Exception, e:
- errorList.append(port)
- continue
- if errorList:
- return JsonResponse({'result': 0, 'description': u"出现上分失败" + errdesc, 'payload': {'errorList':errorList}})
-
- return JsonResponse({'result': 0, 'description': u"上分成功", 'payload': {'errorList':errorList}})
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def getPolicyInfos(request):
- lc = request.GET.get('logicalCode')
- dev = Device.get_dev_by_l(lc)
- box = ActionDeviceBuilder.create_action_device(dev)
- result = box.get_policy_infos()
- return JsonOkResponse(payload=result)
- @error_tolerate(nil=DefaultJsonErrorResponse)
- @permission_required(ROLE.dealer)
- def setPolicyInfos(request):
- payload = json.loads(request.body)
- lc = payload.get('logicalCode')
- dev = Device.get_dev_by_l(lc)
- box = ActionDeviceBuilder.create_action_device(dev)
- try:
- box.set_policy_infos(payload)
- except ServiceException, e:
- return JsonErrorResponse(description=e.result.get('description'))
-
- return JsonOkResponse(description=u'计费配置保存成功')
- @error_tolerate(logger = logger)
- def refundOrderNotifier(request, pay_app_type):
- """
- 退款回调接口(经销商目前只有微信和京东聚合支付微信部分)
- :param request:
- :param pay_app_type:
- :return:
- """
- assert pay_app_type in PayAppType.choices(), 'not support this pay app type({})'.format(pay_app_type)
- notifier_cls = RefundManager().get_notifier(pay_app_type)
- response = notifier_cls(request, lambda filter: RefundDealerRechargeRecord.get_record(**filter)).do(
- refund_post_pay)
- return response
|