123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847 |
- # -*- 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
- def cmp_by_port(x, y):
- if str(x['index']).isdigit() and str(y['index']).isdigit():
- if int(x['index']) < int(y['index']):
- return -1
- elif int(x['index']) > int(y['index']):
- return 1
- return 0
- else:
- if x['index'] < y['index']:
- return -1
- elif x['index'] > y['index']:
- return 1
- return 0
- def charge_pay_coin_unit(p, u):
- """
- 给端口信息中的付费添加上单位
- :param p:
- :param u:
- :return:
- """
- _coins = p.get("coins")
- if not _coins:
- return
- p.update({"coins": "{}{}".format(_coins, u)})
- currentDealer = request.user
- dev = Device.get_dev_by_logicalCode(request.GET.get('logicalCode')) # type: DeviceDict
- group = dev.group # type: GroupDict
- if str(currentDealer.id) == group['ownerId']:
- isManager = True
- else:
- isManager = False
- smartBox = dev.deviceAdapter
- if hasattr(smartBox, 'dealer_get_device_port'):
- portList = getattr(smartBox, 'dealer_get_device_port')()
- return JsonResponse({"result": 1, "description": "", "payload": {"portList": portList}})
- try:
- # 先从设备上取信息,然后从缓存中取信息
- portDict = smartBox.dealer_get_port_status()
- smartBox.async_update_portinfo_from_dev()
- 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 = []
- unit = smartBox.show_pay_unit
- 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 'status' in _info and _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 = smartBox.get_port_using_detail(port, ctrInfo)
- portDetail.update({"index": str(port), "status": 'busy'})
- portList.append(portDetail)
- portList.sort(key=lambda _port: int(_port['index']) if isinstance(_port['index'], str) and _port["index"].isdigit() else _port['index'])
- map(charge_pay_coin_unit, portList, [unit for x in xrange(len(portList))])
- if dev.support_power_graph and (
- 'showPG_in_port_detail' in dev.owner.features or dev.driverCode in [Const.DEVICE_TYPE_CODE_WEIFULE_ANJIAN]):
- for item in portList:
- item['showPG'] = True
- portList.sort(cmp=cmp_by_port)
- 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
|