ReplenishmentAppService.cs 482 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078
  1. using Amazon.Runtime.Internal.Util;
  2. using Business.Core.Enum;
  3. using Business.Core.Utilities;
  4. using Business.Domain;
  5. using Business.Dto;
  6. using Business.EntityFrameworkCore;
  7. using Business.EntityFrameworkCore.SqlRepositories;
  8. using Business.ReplenishmentManagement;
  9. using Business.ResourceExamineManagement;
  10. using Business.ResourceExamineManagement.Dto;
  11. using Business.StructuredDB.MES;
  12. using Business.StructuredDB.MES.IC;
  13. using Business.StructuredDB.Production;
  14. using Business.StructuredDB.Replenishment;
  15. using Business.StructuredDB.SaleFcst;
  16. using Business.StructuredDB.WMS;
  17. using Business.SystemJob;
  18. using Business.SystemJobManagement;
  19. using EFCore.BulkExtensions;
  20. using Microsoft.EntityFrameworkCore;
  21. using Microsoft.EntityFrameworkCore.Metadata.Internal;
  22. using MongoDB.Driver;
  23. using MongoDB.Driver.Linq;
  24. using Newtonsoft.Json;
  25. using NPOI.SS.Formula.Functions;
  26. using System;
  27. using System.Collections;
  28. using System.Collections.Generic;
  29. using System.ComponentModel.Design;
  30. using System.Data;
  31. using System.Linq;
  32. using System.Reflection;
  33. using System.Threading.Tasks;
  34. using Volo.Abp.Application.Services;
  35. using Volo.Abp.DependencyInjection;
  36. using Volo.Abp.Domain.Repositories;
  37. using Volo.Abp.MultiTenancy;
  38. using Volo.Abp.ObjectMapping;
  39. using Volo.Abp.Uow;
  40. using ZstdSharp.Unsafe;
  41. using static Azure.Core.HttpHeader;
  42. using static NetTopologySuite.Geometries.Utilities.GeometryMapper;
  43. namespace Business.Replenishment
  44. {
  45. /// <summary>
  46. /// 产能分析
  47. /// </summary>
  48. public class ReplenishmentAppService : ApplicationService, IReplenishmentAppService, ITransientDependency
  49. {
  50. #region 服务
  51. /// <summary>
  52. /// 雪花算法
  53. /// </summary>
  54. SnowFlake help = new SnowFlake();
  55. private readonly IRepository<ReplenishmentROPWeekPlan, long> _replenishmentROPWeekPlan;
  56. private readonly ISqlRepository<ASNBOLShipperDetail> _ASNBOLShipperDetail;
  57. private readonly ISqlRepository<ASNBOLShipperMaster> _ASNBOLShipperMaster;
  58. private readonly ISqlRepository<InvTransHist> _invTransHist;
  59. private readonly ISqlRepository<InvMaster> _invMaster;
  60. private readonly ISqlRepository<SAPInv> _SAPInv;
  61. private readonly IRepository<srm_purchase, long> _srmPurchase;
  62. /// <summary>
  63. /// 交货计划
  64. /// </summary>
  65. private readonly IRepository<ic_demandschedule, long> _icdemandschedule;
  66. /// <summary>
  67. /// 交货单
  68. /// </summary>
  69. private readonly ISqlRepository<srm_polist_ds> _srmpolistds;
  70. /// <summary>
  71. /// 采购明细表
  72. /// </summary>
  73. private readonly ISqlRepository<PurOrdDetail> _PurOrdDetail;
  74. /// <summary>
  75. /// 采购单表
  76. /// </summary>
  77. private readonly ISqlRepository<PurOrdMaster> _PurOrdMaster;
  78. /// <summary>
  79. /// 优先级配置表
  80. /// </summary>
  81. private readonly ISqlRepository<PriorityCode> _PriorityCode;
  82. private ISqlRepository<NbrMaster> _nbrMaster;
  83. private ISqlRepository<NbrDetail> _nbrDetail;
  84. /// <summary>
  85. /// 送货单子表
  86. /// </summary>
  87. private readonly ISqlRepository<scm_shdzb> _scm_shdzb;
  88. /// <summary>
  89. /// 交货单异常记录表
  90. /// </summary>
  91. private readonly ISqlRepository<DeliveryExceptionMaster> _DeliveryExceptionMaster;
  92. private readonly ISqlRepository<MonthlyShipmentPlan> _monthlyShipmentPlan;
  93. private readonly ISqlRepository<MonthlyShipmentPlanHistory> _monthlyShipmentPlanHistory;
  94. private readonly ISqlRepository<GeneralizedCodeMaster> _generalizedCodeMaster;
  95. private readonly IRepository<mo_ic_item, long> _ic_item;
  96. private readonly IRepository<ic_item, long> _mysql_ic_item;
  97. private readonly ISqlRepository<ItemMaster> _itemMaster;
  98. private readonly IRepository<mo_srm_pr_main, long> _srm_pr_main;
  99. private readonly IRepository<srm_pr_main, long> _mysql_srm_pr_main;
  100. private readonly IRepository<mo_srm_po_occupy, long> _srm_po_occupy;
  101. private readonly IRepository<srm_po_occupy, long> _mysql_srm_po_occupy;
  102. private readonly IRepository<srm_pr_main_occupy, long> _mysql_srm_pr_main_occupy;
  103. private readonly IRepository<mo_mes_morder, long> _mes_morder;
  104. private readonly IRepository<mo_mes_moentry, long> _mes_moentry;
  105. private readonly IRepository<mo_mes_mooccupy, long> _mes_mooccupy;
  106. private readonly IRepository<mes_mooccupy, long> _mysql_mes_mooccupy;
  107. private readonly IRepository<b_bom_pretreatment, long> _mysql_b_bom_pretreatment;
  108. private readonly ISqlRepository<WorkOrdMaster> _workOrdMaster;
  109. private readonly ISqlRepository<ProdLineDetail> _prodLineDetail;
  110. private readonly ISqlRepository<LineMaster> _lineMaster;
  111. private readonly IRepository<mo_ic_bom, long> _ic_bom;
  112. private readonly IRepository<ic_bom, long> _mysql_ic_bom;
  113. private readonly IRepository<mo_ic_bom_child, long> _ic_bom_child;
  114. private readonly IRepository<ic_bom_child, long> _mysql_ic_bom_child;
  115. private readonly ISqlRepository<HolidayMaster> _holidayMaster;
  116. private readonly IRepository<mo_ic_item_stockoccupy, long> _ic_item_stockoccupy;
  117. private readonly IRepository<ic_item_stockoccupy, long> _mysql_ic_item_stockoccupy;
  118. private readonly IRepository<mo_ic_item_stock, long> _ic_item_stock;
  119. private readonly IRepository<ic_item_stock, long> _mysql_ic_item_stock;
  120. private readonly IRepository<mo_ic_substitute, long> _ic_substitute;
  121. private readonly IRepository<mo_ic_substitute_group, long> _ic_substitute_group;
  122. private readonly IRepository<mo_ic_substitute_group_detail, long> _ic_substitute_group_detail;
  123. private readonly IRepository<ic_substitute, long> _mysql_ic_substitute;
  124. private readonly IRepository<ic_substitute_group, long> _mysql_ic_substitute_group;
  125. private readonly IRepository<ic_substitute_group_detail, long> _mysql_ic_substitute_group_detail;
  126. private readonly IRepository<mes_moentry, long> _mysql_mes_moentry;
  127. private readonly ISqlRepository<WorkOrdDetail> _workOrdDetail;
  128. private readonly IRepository<mo_srm_po_list, long> _srm_po_list;
  129. private readonly IRepository<srm_po_list, long> _mysql_srm_po_list;
  130. private readonly ISqlRepository<RoutingOpDetail> _routingOpDetail;
  131. private readonly ISqlRepository<ProductStructureMaster> _productStructureMaster;
  132. private readonly ISqlRepository<ShopCalendarWorkCtr> _shopCalendarWorkCtr;
  133. private readonly ISqlRepository<QualityLineWorkDetail> _qualityLineWorkDetail;
  134. private readonly ISqlRepository<CustMaster> _custMaster;
  135. private readonly IRepository<mo_srm_po_main, long> _srm_po_main;
  136. private readonly IRepository<srm_po_main, long> _mysql_srm_po_main;
  137. private readonly IRepository<mo_srm_purchase, long> _srm_purchase;
  138. private readonly IRepository<srm_purchase, long> _mysql_srm_purchase;
  139. private readonly IRepository<mes_morder, long> _mysql_mes_morder;
  140. private readonly IRepository<crm_seorder, long> _mysql_crm_seorder;
  141. private readonly IRepository<crm_seorderentry, long> _mysql_crm_seorderentry;
  142. private readonly IRepository<ProductionMasterPlan, long> _productionMasterPlan;
  143. private readonly IRepository<ReplenishmentWeekPlan, long> _replenishmentWeekPlan;
  144. private readonly IRepository<b_examine_result, long> _mysql_examine_result;
  145. private readonly IRepository<b_bom_child_examine, long> _mysql_bom_child_examine;
  146. private readonly IRepository<ReplenishmentServiceLevel, long> _replenishmentServiceLevel;
  147. //private readonly IExtSqlRepository<DMS_IN_ITEMMAPPING> _DMS_IN_ITEMMAPPING;
  148. //private readonly IExtSqlRepository<DMS_IN_LOCDETAIL> _DMS_IN_LOCDETAIL;
  149. //private readonly IExtSqlRepository<DMS_IN_SHIPPINGDETAIL> _DMS_IN_SHIPPINGDETAIL;
  150. private readonly IRepository<ReplenishmentTurnOverSet> _ReplenishmentTurnOverSet;
  151. /// <summary>
  152. /// 成品虚拟件工序关系表
  153. /// </summary>
  154. private readonly ISqlRepository<ProductStructureOp> _productStructureOp;
  155. /// <summary>
  156. /// 年度销售预测
  157. /// </summary>
  158. private IRepository<YearDemandManagement, long> _yearDemandManagement;
  159. /// <summary>
  160. /// 年度销售预测历史记录
  161. /// </summary>
  162. private IRepository<YearDemandManagementHistory, long> _yearDemandManagementHistory;
  163. /// <summary>
  164. /// 年度生产大纲
  165. /// </summary>
  166. private IRepository<ReplenishmentAnnualProduction, long> _replenishmentAnnualProduction;
  167. /// <summary>
  168. /// 平台库存表
  169. /// </summary>
  170. private readonly IRepository<WMS_PlatformInventory, long> _PlatformInventory;
  171. /// <summary>
  172. /// 工单工艺路线明细
  173. /// </summary>
  174. private ISqlRepository<WorkOrdRouting> _workOrdRouting;
  175. /// <summary>
  176. /// 排产结果明细
  177. /// </summary>
  178. private ISqlRepository<ScheduleResultOpMaster> _scheduleResultOpMaster;
  179. /// <summary>
  180. /// 排产记录表
  181. /// </summary>
  182. private readonly ISqlRepository<PeriodSequenceDet> _periodSequenceDet;
  183. /// <summary>
  184. /// 计划订单表
  185. /// </summary>
  186. private IRepository<crm_planorder, long> _crm_planorder;
  187. /// <summary>
  188. /// 平台库存表
  189. /// </summary>
  190. private IRepository<WMS_PlatformInventory, long> _platformInventory;
  191. /// <summary>
  192. /// 在途检查
  193. /// </summary>
  194. private readonly PurchaseOrderAppService _purchaseOrderAppService;
  195. /// <summary>
  196. /// 计算BOM平铺物料情况
  197. /// </summary>
  198. private readonly CalcBomViewAppService _CalcBomViewAppService;
  199. /// <summary>
  200. /// 工单App
  201. /// </summary>
  202. private readonly MorderAppService _morderAppService;
  203. /// <summary>
  204. /// 预处理
  205. /// </summary>
  206. private readonly PretreatmentAppService _pretreatmentAppService;
  207. private readonly SerialNumberAppService _serialNumberAppService;
  208. /// <summary>
  209. /// 产能检查
  210. /// </summary>
  211. private readonly ProductExamineAppService _productExamineAppService;
  212. /// <summary>
  213. /// 账号时效性验证
  214. /// </summary>
  215. private readonly AccountValidityAppService _AccountValidityAppService;
  216. /// <summary>
  217. /// 资源检查入参
  218. /// </summary>
  219. private readonly SeorderentryDto param = new SeorderentryDto();
  220. /// <summary>
  221. /// 生产线明细表
  222. /// </summary>
  223. public List<ProdLineDetail> prodLines = new List<ProdLineDetail>();
  224. /// <summary>
  225. /// 标准工艺路径表
  226. /// </summary>
  227. public List<RoutingOpDetail> routingOps = new List<RoutingOpDetail>();
  228. /// <summary>
  229. /// 排产记录表
  230. /// </summary>
  231. public List<PeriodSequenceDet> periodSequences = new List<PeriodSequenceDet>();
  232. /// <summary>
  233. /// 工作日历
  234. /// </summary>
  235. public List<ShopCalendarWorkCtr> calendarWorks = new List<ShopCalendarWorkCtr>();
  236. /// <summary>
  237. /// 休息时间段
  238. /// </summary>
  239. public List<QualityLineWorkDetail> qualityLineWorks = new List<QualityLineWorkDetail>();
  240. private readonly ISqlRepository<ConfigurationItem> _configurationItem;
  241. /// <summary>
  242. /// 节假日
  243. /// </summary>
  244. public List<HolidayMaster> holidays = new List<HolidayMaster>();
  245. private List<ICItemLeadTimeDto> leadTimeList;
  246. private List<mo_srm_purchase> supplierList;
  247. private readonly BusinessBangDbContext _businessBangDbContext;
  248. private readonly BusinessDbContext _businessDbContext;
  249. private readonly ICurrentTenant _currentTenant;
  250. private readonly IUnitOfWorkManager _unitOfWorkManager;
  251. private readonly SystemJobAppService _systemJobAppService;
  252. #endregion
  253. #region 构造函数
  254. /// <summary>
  255. /// 构造函数
  256. /// </summary>
  257. public ReplenishmentAppService(
  258. IRepository<ReplenishmentROPWeekPlan, long> replenishmentROPWeekPlan,
  259. ISqlRepository<ASNBOLShipperDetail> ASNBOLShipperDetail,
  260. ISqlRepository<ASNBOLShipperMaster> ASNBOLShipperMaster,
  261. ISqlRepository<InvTransHist> invTransHist,
  262. IRepository<srm_purchase, long> srmPurchase,
  263. ISqlRepository<MonthlyShipmentPlan> monthlyShipmentPlan,
  264. ISqlRepository<MonthlyShipmentPlanHistory> monthlyShipmentPlanHistory,
  265. ISqlRepository<GeneralizedCodeMaster> generalizedCodeMaster,
  266. ISqlRepository<InvMaster> invMaster,
  267. ISqlRepository<SAPInv> SAPInv,
  268. IRepository<mo_ic_item, long> ic_item,
  269. IRepository<ic_item, long> mysql_ic_item,
  270. ISqlRepository<ItemMaster> itemMaster,
  271. IRepository<mo_srm_pr_main, long> srm_pr_main,
  272. IRepository<srm_pr_main, long> mysql_srm_pr_main,
  273. IRepository<mo_srm_po_occupy, long> srm_po_occupy,
  274. IRepository<srm_po_occupy, long> mysql_srm_po_occupy,
  275. IRepository<srm_pr_main_occupy, long> mysql_srm_pr_main_occupy,
  276. IRepository<mo_mes_morder, long> mes_morder,
  277. IRepository<mo_mes_moentry, long> mes_moentry,
  278. IRepository<mo_mes_mooccupy, long> mes_mooccupy,
  279. IRepository<mes_mooccupy, long> mysql_mes_mooccupy,
  280. IRepository<b_bom_pretreatment, long> mysql_b_bom_pretreatment,
  281. ISqlRepository<WorkOrdMaster> workOrdMaster,
  282. ISqlRepository<ProdLineDetail> prodLineDetail,
  283. ISqlRepository<LineMaster> lineMaster,
  284. IRepository<mo_ic_bom, long> ic_bom,
  285. IRepository<ic_bom, long> mysql_ic_bom,
  286. IRepository<mo_ic_bom_child, long> ic_bom_child,
  287. IRepository<ic_bom_child, long> mysql_ic_bom_child,
  288. ISqlRepository<HolidayMaster> holidayMaster,
  289. IRepository<mo_ic_item_stockoccupy, long> ic_item_stockoccupy,
  290. IRepository<ic_item_stockoccupy, long> mysql_ic_item_stockoccupy,
  291. IRepository<mo_ic_item_stock, long> ic_item_stock,
  292. IRepository<ic_item_stock, long> mysql_ic_item_stock,
  293. IRepository<mo_ic_substitute, long> ic_substitute,
  294. IRepository<mo_ic_substitute_group, long> ic_substitute_group,
  295. IRepository<mo_ic_substitute_group_detail, long> ic_substitute_group_detail,
  296. IRepository<ic_substitute, long> mysql_ic_substitute,
  297. IRepository<ic_substitute_group, long> mysql_ic_substitute_group,
  298. IRepository<ic_substitute_group_detail, long> mysql_ic_substitute_group_detail,
  299. IRepository<mes_moentry, long> mysql_mes_moentry,
  300. ISqlRepository<WorkOrdDetail> workOrdDetail,
  301. IRepository<mo_srm_po_list, long> srm_po_list,
  302. IRepository<srm_po_list, long> mysql_srm_po_list,
  303. ISqlRepository<RoutingOpDetail> routingOpDetail,
  304. ISqlRepository<ProductStructureMaster> productStructureMaster,
  305. ISqlRepository<ShopCalendarWorkCtr> shopCalendarWorkCtr,
  306. ISqlRepository<PeriodSequenceDet> periodSequenceDet,
  307. ISqlRepository<QualityLineWorkDetail> qualityLineWorkDetail,
  308. ISqlRepository<ScheduleResultOpMaster> scheduleResultOpMaster,
  309. IRepository<mo_srm_po_main, long> srm_po_main,
  310. IRepository<srm_po_main, long> mysql_srm_po_main,
  311. IRepository<mo_srm_purchase, long> srm_purchase,
  312. IRepository<srm_purchase, long> mysql_srm_purchase,
  313. IRepository<mes_morder, long> mysql_mes_morder,
  314. IRepository<crm_seorder, long> mysql_crm_seorder,
  315. IRepository<crm_seorderentry, long> mysql_crm_seorderentry,
  316. IRepository<mo_mes_oorder, long> mes_oorder,
  317. IRepository<ProductionMasterPlan, long> productionMasterPlan,
  318. ISqlRepository<ProductStructureOp> productStructureOp,
  319. IRepository<YearDemandManagement, long> yearDemandManagement,
  320. IRepository<ReplenishmentAnnualProduction, long> replenishmentAnnualProduction,
  321. IRepository<YearDemandManagementHistory, long> yearDemandManagementHistory,
  322. IRepository<WMS_PlatformInventory, long> PlatformInventory,
  323. ISqlRepository<WorkOrdRouting> workOrdRouting,
  324. ISqlRepository<CustMaster> custMaster,
  325. IRepository<crm_planorder, long> crm_planorder,
  326. IRepository<WMS_PlatformInventory, long> platformInventory,
  327. IRepository<ReplenishmentWeekPlan, long> replenishmentWeekPlan,
  328. IRepository<b_examine_result, long> mysql_examine_result,
  329. IRepository<b_bom_child_examine, long> mysql_bom_child_examine,
  330. IRepository<ReplenishmentServiceLevel, long> replenishmentServiceLevel,
  331. ISqlRepository<NbrMaster> nbrMaster,
  332. ISqlRepository<NbrDetail> nbrDetail,
  333. //IExtSqlRepository<DMS_IN_ITEMMAPPING> DMS_IN_ITEMMAPPING,
  334. //IExtSqlRepository<DMS_IN_LOCDETAIL> DMS_IN_LOCDETAIL,
  335. //IExtSqlRepository<DMS_IN_SHIPPINGDETAIL> DMS_IN_SHIPPINGDETAIL,
  336. IRepository<ReplenishmentTurnOverSet> ReplenishmentTurnOverSet,
  337. ISqlRepository<ConfigurationItem> configurationItem,
  338. SerialNumberAppService serialNumberAppService,
  339. PretreatmentAppService pretreatmentAppService,
  340. PurchaseOrderAppService purchaseOrderAppService,
  341. CalcBomViewAppService CalcBomViewAppService,
  342. MorderAppService morderAppService,
  343. AccountValidityAppService AccountValidityAppService,
  344. ProductExamineAppService productExamineAppService,
  345. BusinessBangDbContext businessBangDbContext,
  346. BusinessDbContext businessDbContext,
  347. ICurrentTenant currentTenant,
  348. IRepository<ic_demandschedule, long> icdemandschedule,
  349. ISqlRepository<srm_polist_ds> srmpolistds,
  350. ISqlRepository<PurOrdDetail> PurOrdDetail,
  351. ISqlRepository<PurOrdMaster> PurOrdMaster,
  352. ISqlRepository<DeliveryExceptionMaster> DeliveryExceptionMaster,
  353. ISqlRepository<scm_shdzb> scm_shdzb,
  354. IUnitOfWorkManager unitOfWorkManager,
  355. ISqlRepository<PriorityCode> PriorityCode,
  356. SystemJobAppService systemJobAppService)
  357. {
  358. _replenishmentROPWeekPlan = replenishmentROPWeekPlan;
  359. _ASNBOLShipperDetail = ASNBOLShipperDetail;
  360. _ASNBOLShipperMaster = ASNBOLShipperMaster;
  361. _invTransHist = invTransHist;
  362. _srmPurchase = srmPurchase;
  363. _monthlyShipmentPlan = monthlyShipmentPlan;
  364. _monthlyShipmentPlanHistory = monthlyShipmentPlanHistory;
  365. _generalizedCodeMaster = generalizedCodeMaster;
  366. _invMaster = invMaster;
  367. _SAPInv = SAPInv;
  368. _nbrMaster = nbrMaster;
  369. _nbrDetail = nbrDetail;
  370. _ic_item = ic_item;
  371. _mysql_ic_item = mysql_ic_item;
  372. _itemMaster = itemMaster;
  373. _srm_pr_main = srm_pr_main;
  374. _mysql_srm_pr_main = mysql_srm_pr_main;
  375. _srm_po_occupy = srm_po_occupy;
  376. _mysql_srm_po_occupy = mysql_srm_po_occupy;
  377. _mysql_srm_pr_main_occupy = mysql_srm_pr_main_occupy;
  378. _mes_morder = mes_morder;
  379. _mes_moentry = mes_moentry;
  380. _mes_mooccupy = mes_mooccupy;
  381. _mysql_mes_mooccupy = mysql_mes_mooccupy;
  382. _mysql_b_bom_pretreatment = mysql_b_bom_pretreatment;
  383. _workOrdMaster = workOrdMaster;
  384. _scheduleResultOpMaster = scheduleResultOpMaster;
  385. _periodSequenceDet = periodSequenceDet;
  386. _custMaster = custMaster;
  387. _prodLineDetail = prodLineDetail;
  388. _lineMaster = lineMaster;
  389. _ic_bom = ic_bom;
  390. _mysql_ic_bom = mysql_ic_bom;
  391. _ic_bom_child = ic_bom_child;
  392. _mysql_ic_bom_child = mysql_ic_bom_child;
  393. _holidayMaster = holidayMaster;
  394. _ic_item_stockoccupy = ic_item_stockoccupy;
  395. _mysql_ic_item_stockoccupy = mysql_ic_item_stockoccupy;
  396. _ic_item_stock = ic_item_stock;
  397. _mysql_ic_item_stock = mysql_ic_item_stock;
  398. _ic_substitute = ic_substitute;
  399. _ic_substitute_group = ic_substitute_group;
  400. _ic_substitute_group_detail = ic_substitute_group_detail;
  401. _mysql_ic_substitute = mysql_ic_substitute;
  402. _mysql_ic_substitute_group = mysql_ic_substitute_group;
  403. _mysql_ic_substitute_group_detail = mysql_ic_substitute_group_detail;
  404. _mysql_mes_moentry = mysql_mes_moentry;
  405. _workOrdDetail = workOrdDetail;
  406. _srm_po_list = srm_po_list;
  407. _mysql_srm_po_list = mysql_srm_po_list;
  408. _routingOpDetail = routingOpDetail;
  409. _productStructureMaster = productStructureMaster;
  410. _shopCalendarWorkCtr = shopCalendarWorkCtr;
  411. _qualityLineWorkDetail = qualityLineWorkDetail;
  412. _srm_po_main = srm_po_main;
  413. _mysql_srm_po_main = mysql_srm_po_main;
  414. _srm_purchase = srm_purchase;
  415. _mysql_srm_purchase = mysql_srm_purchase;
  416. _mysql_mes_morder = mysql_mes_morder;
  417. _mysql_crm_seorder = mysql_crm_seorder;
  418. _mysql_crm_seorderentry = mysql_crm_seorderentry;
  419. _productionMasterPlan = productionMasterPlan;
  420. _replenishmentWeekPlan = replenishmentWeekPlan;
  421. _mysql_examine_result = mysql_examine_result;
  422. _mysql_bom_child_examine = mysql_bom_child_examine;
  423. _replenishmentServiceLevel = replenishmentServiceLevel;
  424. _productStructureOp = productStructureOp;
  425. _PlatformInventory = PlatformInventory;
  426. _workOrdRouting = workOrdRouting;
  427. _ASNBOLShipperDetail = ASNBOLShipperDetail;
  428. _yearDemandManagement = yearDemandManagement;
  429. _yearDemandManagementHistory = yearDemandManagementHistory;
  430. _replenishmentAnnualProduction = replenishmentAnnualProduction;
  431. _holidayMaster = holidayMaster;
  432. _crm_planorder = crm_planorder;
  433. _platformInventory = platformInventory;
  434. //_DMS_IN_ITEMMAPPING = DMS_IN_ITEMMAPPING;
  435. //_DMS_IN_LOCDETAIL = DMS_IN_LOCDETAIL;
  436. //_DMS_IN_SHIPPINGDETAIL = DMS_IN_SHIPPINGDETAIL;
  437. _ReplenishmentTurnOverSet = ReplenishmentTurnOverSet;
  438. _configurationItem = configurationItem;
  439. _serialNumberAppService = serialNumberAppService;
  440. _pretreatmentAppService = pretreatmentAppService;
  441. _CalcBomViewAppService = CalcBomViewAppService;
  442. _morderAppService = morderAppService;
  443. _AccountValidityAppService = AccountValidityAppService;
  444. _purchaseOrderAppService = purchaseOrderAppService;
  445. _productExamineAppService = productExamineAppService;
  446. _currentTenant = currentTenant;
  447. _businessBangDbContext = businessBangDbContext;
  448. _businessDbContext = businessDbContext;
  449. _unitOfWorkManager = unitOfWorkManager;
  450. _icdemandschedule = icdemandschedule;
  451. _srmpolistds = srmpolistds;
  452. _PurOrdDetail = PurOrdDetail;
  453. _PurOrdMaster = PurOrdMaster;
  454. _DeliveryExceptionMaster = DeliveryExceptionMaster;
  455. _scm_shdzb = scm_shdzb;
  456. _PriorityCode = PriorityCode;
  457. _systemJobAppService = systemJobAppService;
  458. }
  459. #endregion
  460. /// <summary>
  461. /// 生成年度生产大纲
  462. /// </summary>
  463. /// <param name="input"></param>
  464. /// <returns></returns>
  465. /// <exception cref="NotImplementedException"></exception>
  466. public async Task<string> SaveAnnualProductionOutline(InputDto input)
  467. {
  468. //来自定时任务的请求
  469. if (input.year == 0 && input.month == 0)
  470. {
  471. input.year = DateTime.Now.Year;
  472. input.month = DateTime.Now.Month;
  473. }
  474. //每年10月份做下一年的销售预测
  475. if (DateTime.Now.Month >= 10)
  476. {
  477. input.year = DateTime.Now.AddYears(1).Year;
  478. input.month = DateTime.Now.Month;
  479. }
  480. //获取当前导入或修改数据
  481. List<YearDemandManagement> yearDemands = _yearDemandManagement.GetListAsync(p => p.Year == input.year && p.factory_id == input.factory_id && !p.IsDeleted).Result.OrderBy(p => p.OrderNum).ThenBy(o => o.PlanMonth).ToList();
  482. if (yearDemands == null || yearDemands.Count == 0)
  483. {
  484. input.year = DateTime.Now.Year;
  485. input.month = DateTime.Now.Month;
  486. yearDemands = _yearDemandManagement.GetListAsync(p => p.Year == input.year && p.factory_id == input.factory_id && !p.IsDeleted).Result.OrderBy(p => p.OrderNum).ThenBy(o => o.PlanMonth).ToList();
  487. }
  488. //标准工艺路径表
  489. var sapItemList = yearDemands.Select(m => m.SAPItemNumber).Distinct().ToList();
  490. var planList = _mysql_ic_item.GetListAsync(a => sapItemList.Contains(a.number) && a.factory_id == input.factory_id && !a.IsDeleted).Result.ToList();
  491. var bomList = _mysql_ic_bom.GetListAsync(a => sapItemList.Contains(a.item_number) && !a.IsDeleted && a.factory_id == input.factory_id).Result;
  492. var planItemList = planList.Select(a => a.number).Distinct().ToList();
  493. var expectedList = sapItemList.Except(planItemList).ToList();
  494. if (expectedList.Count > 0)
  495. {
  496. return "年度销售预测物料" + string.Join(",", expectedList) + "在DOP物料表找不到!";
  497. }
  498. var bomItemList = bomList.Select(a => a.item_number).Distinct().ToList();
  499. var expectedBOMList = sapItemList.Except(bomItemList).ToList();
  500. if (expectedBOMList.Count > 0)
  501. {
  502. return "年度销售预测物料" + string.Join(",", expectedBOMList) + "在BOM没有维护!";
  503. }
  504. var itemMasterList = _itemMaster.Select(i => sapItemList.Contains(i.ItemNum) && i.Domain == input.factory_id.ToString());
  505. List<RoutingOpDetail> routingOps = _routingOpDetail.Select(p => sapItemList.Contains(p.RoutingCode) && p.Domain == input.factory_id.ToString() && p.IsActive);
  506. var routingOpList = routingOps.Where(x => x.Ufld1 == "组装" && x.MilestoneOp).ToList();
  507. //生产线明细表
  508. List<ProdLineDetail> prodLines = _prodLineDetail.Select(p => sapItemList.Contains(p.Part) && p.Domain == input.factory_id.ToString() && p.IsActive && routingOpList.Select(m => m.Op).Contains(p.Op)).OrderBy(x => x.Sequence).ToList();
  509. List<LineMaster> lineMasters = _lineMaster.Select(p => prodLines.Select(a => a.Line).Distinct().ToList().Contains(p.Line) && p.Domain == input.factory_id.ToString() && p.IsActive).ToList();
  510. List<InvMaster> locations = _invMaster.Select(x => sapItemList.Contains(x.ItemNum) && x.Domain == input.factory_id.ToString() && x.IsActive).ToList();
  511. //平台库存
  512. //var DMSItemList = _DMS_IN_ITEMMAPPING.Select(a => sapItemList.Contains(a.CfnERPCode));
  513. //var gkhwStock = _DMS_IN_LOCDETAIL.Select(a => (a.DealerCode == "RQ000005" || a.DealerCode == "RQ000002"));
  514. //var sapInvList = _SAPInv.Select(a => a.WERKS == input.factory_id.ToString() && sapItemList.Contains(a.MATNR) && (a.SOBKZ.ToUpper() == "O"));
  515. // 获取某年某月的起始日期和结束日期
  516. DateTime start = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
  517. DateTime end = start.AddMonths(1).AddDays(-1);
  518. //取当月发货出库记录
  519. var shipList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.RealQty > 0 && yearDemands.Select(p => p.SAPItemNumber).Contains(a.ContainerItem)).Where(s => s.ShipDate >= start && s.ShipDate <= end);
  520. #region 在制数量
  521. //获取在制数量 获取工单数取每年4月到12月底的工单
  522. DateTime startYear = new DateTime(DateTime.Now.AddYears(-1).Year, 4, 1);
  523. DateTime endYear = new DateTime(DateTime.Now.Year, 12, 31);
  524. //List<WorkOrdRouting> workOrdRoutings = _workOrdRouting.Select(x => x.IsActive && x.QtyComplete > 0 && x.Domain == input.factory_id.ToString()).Where(p => p.DueDate >= startYear && p.DueDate <= endYear).ToList();
  525. decimal? InProductionQty = 0.00m;
  526. //var workOrds = workOrdRoutings.GroupBy(x => x.WorkOrd).ToList();
  527. Dictionary<string, decimal> dictInProduction = new Dictionary<string, decimal>();
  528. ////按照工单循环
  529. ////某工单10-90工序 Max(10-80工序QtyComplete)-90工序QtyComplete =在制数量
  530. //foreach (var item in workOrds)
  531. //{
  532. // var workOrdRoutingList = workOrdRoutings.Where(x => x.WorkOrd == item.Key).OrderByDescending(o => o.OP).ToList();
  533. // //找出最大工序
  534. // var MaxOp = workOrdRoutingList.FirstOrDefault();
  535. // //查询出其他工序最大值
  536. // var MaxQtyComplete = workOrdRoutingList.Where(x => x.RecID != MaxOp.RecID).ToList().Max(o => o.QtyComplete);
  537. // InProductionQty += MaxQtyComplete - MaxOp.QtyComplete;
  538. // if (dictInProduction.ContainsKey(MaxOp.ItemNum))
  539. // {
  540. // dictInProduction[MaxOp.ItemNum] += InProductionQty.Value;
  541. // }
  542. // else
  543. // {
  544. // dictInProduction.Add(MaxOp.ItemNum, InProductionQty.Value);
  545. // }
  546. //}
  547. List<WorkOrdMaster> workOrdMasters = _workOrdMaster.Select(x => x.IsActive && x.Status != "C" && x.QtyOrded - x.QtyCompleted > 0 && x.Domain == input.factory_id.ToString()).Where(p => p.DueDate >= startYear && p.DueDate <= endYear).ToList();
  548. var workOrds = workOrdMasters.GroupBy(x => x.WorkOrd).ToList();
  549. //按照工单循环
  550. //某工单10-90工序 Max(10-80工序QtyComplete)-90工序QtyComplete =在制数量
  551. foreach (var item in workOrds)
  552. {
  553. //查询出其他工序最大值
  554. var works = workOrdMasters.Where(x => x.WorkOrd == item.Key).ToList().FirstOrDefault();
  555. InProductionQty += works.QtyOrded - works.QtyCompleted;
  556. if (dictInProduction.ContainsKey(works.ItemNum))
  557. {
  558. dictInProduction[works.ItemNum] += InProductionQty.Value;
  559. }
  560. else
  561. {
  562. dictInProduction.Add(works.ItemNum, InProductionQty.Value);
  563. }
  564. }
  565. #endregion
  566. //年度生产大纲实体
  567. List<ReplenishmentAnnualProduction> annualProductionOutlines = new List<ReplenishmentAnnualProduction>();
  568. List<YearDemandManagement> frontYearDemand = new List<YearDemandManagement>();
  569. for (int i = 0; i < yearDemands.Count; i++)
  570. {
  571. if (yearDemands.Where(a => a.SAPItemNumber == yearDemands[i].SAPItemNumber).Count() != 12)
  572. {
  573. return "年度销售预测物料" + yearDemands[i].SAPItemNumber + "年度的12个月数据不完整或者存在重复物料!";
  574. }
  575. frontYearDemand.Add(yearDemands[i]);
  576. var routingOp = routingOps.Where(x => x.RoutingCode == yearDemands[i].SAPItemNumber).ToList();
  577. //组装标准工时
  578. var Assembly = routingOp.Where(x => x.Ufld1 == "组装" && x.MilestoneOp).FirstOrDefault();
  579. //热封标准工时
  580. var HeatSealing = routingOp.Where(x => x.Ufld1 == "热封" && x.MilestoneOp).FirstOrDefault();
  581. //包装标准工时
  582. var Packaging = routingOp.Where(x => x.Ufld1 == "包装" && x.MilestoneOp).FirstOrDefault();
  583. var prodLine = prodLines.Where(x => x.Part == yearDemands[i].SAPItemNumber).OrderBy(x => x.Sequence).FirstOrDefault();
  584. //不同库位库存数量
  585. //5008成品线边库,8001成品合格库,8000成品待检
  586. var locationList = locations.Where(x => x.ItemNum == yearDemands[i].SAPItemNumber && (x.Location == "5008" || x.Location == "5009" || x.Location == "5010" || x.Location == "8000" || x.Location == "8001" || x.Location == "8002" || x.Location == "8002" || x.Location == "8003" || x.Location == "8004" || x.Location == "8005")).ToList();
  587. ////平台数据
  588. //decimal? hwStock = 0;
  589. //if (DMSItemList.Find(d => d.CfnERPCode == yearDemands[i].SAPItemNumber) != null)
  590. //{
  591. // var itemDMS = gkhwStock.Where(o => o.UPN == DMSItemList.Find(d => d.CfnERPCode == yearDemands[i].SAPItemNumber).CfnCode && o.DealerCode == "RQ000002").ToList();
  592. // if (itemDMS.Count > 0)
  593. // {
  594. // var maxDate = itemDMS.OrderByDescending(i => i.InventoryDate).First();
  595. // hwStock = itemDMS.Where(i => i.InventoryDate == maxDate.InventoryDate).Sum(q => q.Qty);
  596. // }
  597. //}
  598. //decimal? gkStock = 0;
  599. //if (DMSItemList.Find(d => d.CfnERPCode == yearDemands[i].SAPItemNumber) != null)
  600. //{
  601. // var itemDMS = gkhwStock.Where(o => o.UPN == DMSItemList.Find(d => d.CfnERPCode == yearDemands[i].SAPItemNumber).CfnCode && o.DealerCode == "RQ000005").ToList();
  602. // if (itemDMS.Count > 0)
  603. // {
  604. // var maxDate = itemDMS.OrderByDescending(i => i.InventoryDate).First();
  605. // gkStock = itemDMS.Where(i => i.InventoryDate == maxDate.InventoryDate).Sum(q => q.Qty);
  606. // }
  607. //}
  608. //销售预测 对应 Excel中公式 AVERAGE 如果预测为0不参与计算排产批量
  609. var QtySum = yearDemands.Where(x => x.SAPItemNumber == yearDemands[i].SAPItemNumber && x.Qty > 0).ToList();
  610. //排产批量:(AVG(1 - 12月销售预测)/ 100 )=(0.45 = 1 小数向上取整) *100 = 100
  611. decimal pcpl = 0;
  612. if (QtySum != null && QtySum.Count > 0)
  613. {
  614. pcpl = 1;//Math.Ceiling(QtySum.Average(p => p.Qty));
  615. }
  616. //库存合计 + 在制+已发货 + 灭菌中
  617. var ship = shipList.Where(x => x.ContainerItem == yearDemands[i].SAPItemNumber).ToList();
  618. decimal itemInProduct = 0;
  619. if (dictInProduction.ContainsKey(yearDemands[i].SAPItemNumber))
  620. {
  621. itemInProduct = dictInProduction[yearDemands[i].SAPItemNumber];
  622. }
  623. decimal? InSterilizationQty = 0.00m;
  624. //if (sapInvList.Count > 0 && sapInvList.Any(a => a.MATNR == yearDemands[i].SAPItemNumber))
  625. //{
  626. // InSterilizationQty = sapInvList.Where(a => a.MATNR == yearDemands[i].SAPItemNumber && a.SOBKZ.ToUpper() == "O").Sum(x => Convert.ToDecimal(x.LABST) + Convert.ToDecimal(x.INSME) + Convert.ToDecimal(x.SPEME));
  627. //}
  628. //+ gkStock + hwStock
  629. var locationSum = (locationList.Count == 0 ? 0 : locationList.Sum(x => x.AvailStatusQty.GetValueOrDefault() + x.Assay.GetValueOrDefault())) + (ship.Count == 0 ? 0 : ship.Sum(x => x.QtyToShip)) + itemInProduct + InSterilizationQty;
  630. //前面N个月的生产数量
  631. var frontQtySum = annualProductionOutlines.Where(a => a.SAPItemNumber == yearDemands[i].SAPItemNumber).Sum(x => x.Qty);
  632. //生产数量:3月为例子,if((库存合计和前2月生产数量)-(前2个月销售预测数据)-当月销售预测数据 / 2 < 0)
  633. // { 排产批量 * ((-(库存合计+前12个月生产数量)) + (前12个月销售预测) + 当月销售预测 / 2 ) / 排产批量 ) } else {0}
  634. decimal ProduceQty = 0.00m;
  635. decimal NextMonthQty = 0.00m;
  636. if (yearDemands[i].PlanMonth.Substring(5) != "12")
  637. {
  638. NextMonthQty = yearDemands[i + 1].Qty;
  639. }
  640. else
  641. {
  642. NextMonthQty = pcpl;
  643. }
  644. //判断库存是否满足需要,满足则不用生产
  645. //安全库存
  646. decimal? safeQty = itemMasterList.Find(a => a.ItemNum == yearDemands[i].SAPItemNumber)?.SafetyStk;
  647. //前N个月的需求数量
  648. decimal frontYearDemandQty = frontYearDemand.Where(f => f.SAPItemNumber == yearDemands[i].SAPItemNumber).Sum(m => m.Qty);
  649. if (locationSum.GetValueOrDefault() + frontQtySum - safeQty - frontYearDemandQty - NextMonthQty / 2 < 0)
  650. {
  651. if (pcpl == 0)
  652. {
  653. ProduceQty = 0;
  654. }
  655. else
  656. {
  657. ProduceQty = Math.Ceiling((-locationSum.GetValueOrDefault() - frontQtySum + safeQty.GetValueOrDefault() + frontYearDemandQty + NextMonthQty / 2) / pcpl) * pcpl;
  658. }
  659. }
  660. //生成年度生产大纲
  661. ReplenishmentAnnualProduction annualProductionOutline = new ReplenishmentAnnualProduction();
  662. annualProductionOutline.Year = yearDemands[i].Year;
  663. annualProductionOutline.Area = yearDemands[i].Area;
  664. annualProductionOutline.ProdLine = yearDemands[i].ProdLine;
  665. annualProductionOutline.ProdRange = yearDemands[i].ProdRange;
  666. if (prodLine == null || lineMasters.Find(b => b.Line == prodLine.Line) == null)
  667. {
  668. annualProductionOutline.WorkshopLine = "";
  669. }
  670. else
  671. {
  672. annualProductionOutline.WorkshopLine = lineMasters.Find(b => b.Line == prodLine.Line).Describe;
  673. }
  674. annualProductionOutline.SAPItemNumber = yearDemands[i].SAPItemNumber;
  675. annualProductionOutline.Model = yearDemands[i].Model;
  676. annualProductionOutline.Languages = yearDemands[i].Languages;
  677. annualProductionOutline.PlanMonth = yearDemands[i].PlanMonth;
  678. annualProductionOutline.Qty = ProduceQty;
  679. annualProductionOutline.StandardHours = (Assembly == null ? 0 : Assembly.RunTime) + (HeatSealing == null ? 0 : HeatSealing.RunTime) + (Packaging == null ? 0 : Packaging.RunTime);
  680. //组装热封包装工时乘以数量 =单月工时
  681. annualProductionOutline.AssemblyHours = Assembly == null ? 0 : Assembly.RunTime * ProduceQty;
  682. annualProductionOutline.HeatSealingHours = HeatSealing == null ? 0 : HeatSealing.RunTime * ProduceQty;
  683. annualProductionOutline.PackagingHours = Packaging == null ? 0 : Packaging.RunTime * ProduceQty;
  684. annualProductionOutline.Totalhours = annualProductionOutline.AssemblyHours + annualProductionOutline.HeatSealingHours + annualProductionOutline.Totalhours;
  685. annualProductionOutline.OrderNum = yearDemands[i].OrderNum;
  686. annualProductionOutline.create_time = DateTime.Now;
  687. annualProductionOutline.tenant_id = input.tenant_id;
  688. annualProductionOutline.company_id = input.company_id;
  689. annualProductionOutline.factory_id = input.factory_id;
  690. annualProductionOutline.org_id = input.org_id;
  691. annualProductionOutlines.Add(annualProductionOutline);
  692. }
  693. //保存数据
  694. using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
  695. {
  696. try
  697. {
  698. var toDelete = _businessDbContext.ReplenishmentAnnualProduction.Where(a => a.Year == input.year && a.factory_id == input.factory_id).ToList();
  699. await _businessDbContext.BulkDeleteAsync(toDelete);
  700. await _businessDbContext.AddRangeAsync(annualProductionOutlines);
  701. await _businessDbContext.SaveChangesAsync();
  702. //await CalcLongPeriodItemPR(input);
  703. await CalcROP(input);
  704. await SaveProductionMasterPlan(input, annualProductionOutlines);
  705. //await CalcWeekPlan(input);
  706. await unitOfWork.CompleteAsync();
  707. }
  708. catch (Exception e)
  709. {
  710. unitOfWork.Dispose();
  711. new NLogHelper("AnnualProductionOutlineAppService").WriteLog("SaveAnnualProductionOutline", "【" + input.year + "年" + "】年度生成大纲生成失败:" + e.Message, _currentTenant.Id.ToString());
  712. return "NO|" + e.Message;
  713. };
  714. }
  715. return "OK";
  716. }
  717. /// <summary>
  718. /// 生成主计划
  719. /// </summary>
  720. /// <param name="input"></param>
  721. /// <returns></returns>
  722. public async Task<string> SaveProductionMasterPlan(InputDto input, List<ReplenishmentAnnualProduction> annual)
  723. {
  724. //来自定时任务的请求
  725. if (input.year == 0 && input.month == 0)
  726. {
  727. input.year = DateTime.Now.Year;
  728. input.month = DateTime.Now.Month;
  729. }
  730. //计算当前年月的N0,N+1,N+2
  731. List<string> planMons = GetPlanMonth(4);
  732. List<ProductionMasterPlan> productionMasters = new List<ProductionMasterPlan>();
  733. List<ProductionMasterPlan> pre3MonthPlan = _productionMasterPlan.GetListAsync(a => GetPlanMonth(-3).Contains(a.PlanMonth) && a.factory_id == input.factory_id).Result;
  734. //N0,N+1,N+2月度发货计划
  735. var annualProduction = new List<MonthlyShipmentPlan>();
  736. foreach (var itemMonth in planMons)
  737. {
  738. var annualProductionMonth = _monthlyShipmentPlan.Select(x => itemMonth == x.PlanMonth && !x.IsDeleted && x.factory_id == input.factory_id).OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
  739. if (annualProductionMonth != null && annualProductionMonth.Count > 0)
  740. {
  741. annualProduction.AddRange(annualProductionMonth);
  742. }
  743. else
  744. {
  745. var MaxVersion = _monthlyShipmentPlanHistory.Select(a => a.factory_id == input.factory_id && !a.IsDeleted).Max(b => b.VERSION);
  746. if (!string.IsNullOrEmpty(MaxVersion))
  747. {
  748. var annualProductionMonthHistory = _monthlyShipmentPlanHistory.Select(x => itemMonth == x.PlanMonth && x.VERSION == MaxVersion && !x.IsDeleted && x.factory_id == input.factory_id).OrderByDescending(v => v.VERSION).ThenBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
  749. if (annualProductionMonthHistory != null && annualProductionMonthHistory.Count > 0)
  750. {
  751. var returnlist = ObjectMapper.Map<List<MonthlyShipmentPlanHistory>, List<MonthlyShipmentPlan>>(annualProductionMonthHistory);
  752. annualProduction.AddRange(returnlist);
  753. }
  754. }
  755. }
  756. }
  757. annualProduction = annualProduction.OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
  758. var productionMasterPlan = _productionMasterPlan.GetListAsync(x => planMons.Contains(x.PlanMonth) && !x.IsDeleted && x.factory_id == input.factory_id).Result.OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
  759. List<InvMaster> locations = _invMaster.Select(x => annualProduction.Select(m => m.SAPItemNumber).Contains(x.ItemNum) && x.Domain == input.factory_id.ToString() && x.IsActive).ToList();
  760. var InProdcutQty = GetInProdcutQty(annualProduction.Select(m => m.SAPItemNumber).ToList(), input);
  761. var itemStock = CalcStock(annualProduction.Select(m => m.SAPItemNumber).Distinct().ToList(), input);
  762. _productExamineAppService.routingOps = _routingOpDetail.Select(p => p.Domain == input.factory_id.ToString()).ToList();
  763. //主生产计划渠道合并,只考虑瑞奇库存不考虑国科海王库存
  764. List<MonthlyShipmentPlan> shipList = new List<MonthlyShipmentPlan>();
  765. foreach (var item in annualProduction)
  766. {
  767. if (shipList.Any(a => a.SAPItemNumber == item.SAPItemNumber && a.PlanMonth == item.PlanMonth))
  768. {
  769. shipList.Find(b => b.SAPItemNumber == item.SAPItemNumber && b.PlanMonth == item.PlanMonth).Qty += item.Qty;
  770. }
  771. else
  772. {
  773. shipList.Add(item);
  774. }
  775. }
  776. shipList.OrderBy(a => a.PlanMonth);
  777. var shipItemList = shipList.Select(a => a.SAPItemNumber).Distinct().ToList();
  778. var ropPlan = _replenishmentROPWeekPlan.GetListAsync(x => shipItemList.Contains(x.number) && planMons.Contains(x.planmonth) && !x.IsDeleted && x.factory_id == input.factory_id).Result;
  779. //var sapInvList = _SAPInv.Select(a => a.WERKS == input.factory_id.ToString() && shipItemList.Contains(a.MATNR) && (a.SOBKZ.ToUpper() == "O"));
  780. foreach (var item in shipList)
  781. {
  782. var ropItem = ropPlan.Find(x => x.number == item.SAPItemNumber);
  783. if (ropItem != null)
  784. {
  785. ProductionMasterPlan plan = new ProductionMasterPlan();
  786. plan.Area = item.Area;
  787. plan.ProdLine = item.ProdLine;
  788. plan.ProdRange = item.ProdRange;
  789. plan.WorkshopLine = annual.Find(a => a.PlanMonth == item.PlanMonth && a.SAPItemNumber == item.SAPItemNumber)?.WorkshopLine;
  790. if (plan.WorkshopLine == null)
  791. {
  792. plan.WorkshopLine = "";
  793. }
  794. plan.ItemNumber = item.SAPItemNumber;
  795. plan.Model = item.Model;
  796. plan.Languages = item.Languages;
  797. plan.PlanMonth = item.PlanMonth;
  798. plan.PlanShipQty = item.Qty;
  799. var preMonth = Convert.ToDateTime($"{plan.PlanMonth}-01").AddMonths(-1);
  800. var preMonthStr = $"{preMonth.Year}-{preMonth.Month}";
  801. var preMaster = productionMasters.Find(t => t.ItemNumber == plan.ItemNumber && t.PlanMonth == preMonthStr && t.factory_id == input.factory_id);
  802. var preStock = pre3MonthPlan.Find(t => t.ItemNumber == plan.ItemNumber && t.PlanMonth == preMonthStr && t.factory_id == input.factory_id);
  803. if (preMaster != null)
  804. {
  805. plan.PlanProductQty = Math.Ceiling(item.Qty -
  806. (
  807. preMaster.PlanStockQty -1
  808. //ropItem.security_stock.GetValueOrDefault()
  809. ));//发货计划-(上个月期末库存作为本月期初库存-安全库存)
  810. if (plan.PlanProductQty < 0)
  811. {
  812. plan.PlanProductQty = 0;
  813. }
  814. plan.PlanStockQty = Math.Ceiling(preMaster.PlanStockQty + plan.PlanProductQty - item.Qty);
  815. }
  816. else if (preStock != null)
  817. {
  818. plan.PlanProductQty = Math.Ceiling(item.Qty -
  819. (
  820. preStock.PlanStockQty -1
  821. //ropItem.security_stock.GetValueOrDefault()
  822. ));//发货计划-(上个月期末库存作为本月期初库存-安全库存)
  823. if (plan.PlanProductQty < 0)
  824. {
  825. plan.PlanProductQty = 0;
  826. }
  827. plan.PlanStockQty = Math.Ceiling(preStock.PlanStockQty + plan.PlanProductQty - item.Qty);
  828. }
  829. else
  830. {
  831. decimal itemStockQty = 0;
  832. if (itemStock.Any(a => a.ItemNumber == item.SAPItemNumber))
  833. {
  834. itemStockQty = itemStock.Find(a => a.ItemNumber == item.SAPItemNumber).Qty;
  835. }
  836. decimal itemInProdcutQty = 0;
  837. if (InProdcutQty.Any(a => a.ItemNumber == item.SAPItemNumber))
  838. {
  839. itemInProdcutQty = InProdcutQty.Find(a => a.ItemNumber == item.SAPItemNumber).Qty;
  840. }
  841. plan.PlanProductQty = item.Qty -
  842. (itemStockQty + itemInProdcutQty - 1//ropItem.security_stock.GetValueOrDefault()
  843. );//发货计划-(库存+在制-安全库存)
  844. if (plan.PlanProductQty < 0)
  845. plan.PlanProductQty = 0;
  846. plan.PlanStockQty = Math.Ceiling(
  847. itemStock.Find(a => a.ItemNumber == item.SAPItemNumber).Qty +
  848. InProdcutQty.Find(a => a.ItemNumber == item.SAPItemNumber).Qty +
  849. plan.PlanProductQty - item.Qty);
  850. }
  851. if (locations.FirstOrDefault(a => a.ItemNum == item.SAPItemNumber && a.Location == "8001") != null)
  852. {
  853. plan.Inventory = locations.Where(a => a.ItemNum == item.SAPItemNumber && a.Location == "8001").Sum(c => c.AvailStatusQty.GetValueOrDefault() + c.Assay.GetValueOrDefault());
  854. }
  855. else
  856. {
  857. plan.Inventory = 0;
  858. }
  859. if (locations.FirstOrDefault(a => a.ItemNum == item.SAPItemNumber && a.Location == "8000") != null)
  860. {
  861. plan.Inventory1 = locations.Where(a => a.ItemNum == item.SAPItemNumber && a.Location == "8000").Sum(c => c.AvailStatusQty.GetValueOrDefault() + c.Assay.GetValueOrDefault());
  862. }
  863. else
  864. {
  865. plan.Inventory1 = 0;
  866. }
  867. if (locations.FirstOrDefault(a => a.ItemNum == item.SAPItemNumber && a.Location == "5008") != null)
  868. {
  869. plan.Inventory2 = locations.Where(a => a.ItemNum == item.SAPItemNumber && a.Location == "5008").Sum(c => c.AvailStatusQty.GetValueOrDefault() + c.Assay.GetValueOrDefault());
  870. }
  871. else
  872. {
  873. plan.Inventory2 = 0;
  874. }
  875. decimal InSterilizationQty = 0.00m;
  876. //if (sapInvList.Count > 0 && sapInvList.Any(a => a.MATNR == item.SAPItemNumber && a.SOBKZ.ToUpper() == "O"))
  877. //{
  878. // InSterilizationQty = sapInvList.Where(a => a.MATNR == item.SAPItemNumber && a.SOBKZ.ToUpper() == "O").Sum(x => Convert.ToDecimal(x.LABST) + Convert.ToDecimal(x.INSME) + Convert.ToDecimal(x.SPEME));
  879. //}
  880. plan.DuringSterilization = InSterilizationQty;
  881. plan.InProduction = InProdcutQty.Find(a => a.ItemNumber == item.SAPItemNumber).Qty;
  882. if (pre3MonthPlan.Where(a => a.ItemNumber == item.SAPItemNumber).Count() > 0)
  883. {
  884. plan.EconomicLotSize = pre3MonthPlan.Where(a => a.ItemNumber == item.SAPItemNumber).Average(a => a.PlanProductQty);
  885. }
  886. else
  887. {
  888. plan.EconomicLotSize = plan.PlanProductQty;
  889. }
  890. plan.tenant_id = input.tenant_id;
  891. plan.factory_id = input.factory_id;
  892. plan.company_id = input.company_id;
  893. plan.org_id = input.org_id;
  894. plan.create_time = DateTime.Now;
  895. plan.OrderNum = item.OrderNum;
  896. ProdExamineParamDto prodExamine = new ProdExamineParamDto()
  897. {
  898. ItemNum = plan.ItemNumber,
  899. PlanStart = DateTime.Today,
  900. QtyOrd = plan.PlanProductQty,
  901. Domain = input.factory_id.ToString()
  902. };
  903. int make_time = _productExamineAppService.ProductTime(prodExamine);
  904. plan.ProductionTime = make_time;
  905. productionMasters.Add(plan);
  906. }
  907. else
  908. {
  909. new NLogHelper("AnnualProductionOutlineAppService").WriteLog("SaveProductionMasterPlan", "【" + input.year + "年" + "】主计划找不到发货计划物料:" + item.SAPItemNumber, _currentTenant.Id.ToString());
  910. }
  911. }
  912. //保存数据
  913. using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
  914. {
  915. try
  916. {
  917. var planList = productionMasters.Select(a => a.PlanMonth).ToList();
  918. await _productionMasterPlan.DeleteAsync(a => planList.Contains(a.PlanMonth) && a.factory_id == input.factory_id);
  919. await _businessDbContext.AddRangeAsync(productionMasters);
  920. await _businessDbContext.SaveChangesAsync();
  921. await unitOfWork.CompleteAsync();
  922. }
  923. catch (Exception e)
  924. {
  925. unitOfWork.Dispose();
  926. new NLogHelper("AnnualProductionOutlineAppService").WriteLog("SaveProductionMasterPlan", "【" + input.year + "年" + "】主计划生成失败:" + e.Message, _currentTenant.Id.ToString());
  927. return "NO|" + e.Message;
  928. };
  929. }
  930. return "OK";
  931. }
  932. /// <summary>
  933. /// 获取物料在制数量
  934. /// </summary>
  935. /// <param name="itemNumbers"></param>
  936. /// <param name="input"></param>
  937. /// <returns></returns>
  938. public List<EOPDto> GetProdcutQty(List<string> itemNumbers, InputDto input)
  939. {
  940. List<EOPDto> itemQty = new List<EOPDto>();
  941. List<WorkOrdMaster> workOrdMasters = _workOrdMaster.Select(x => x.Domain == param.factoryId.ToString() && string.IsNullOrEmpty(x.Typed) == true && !string.IsNullOrEmpty(x.Status) && x.Status.ToUpper() != "C" && x.Status.ToUpper() != "P" && x.IsActive).ToList();
  942. var workOrds = workOrdMasters.GroupBy(x => x.WorkOrd).ToList();
  943. Dictionary<string, decimal> dictInProduction = new Dictionary<string, decimal>();
  944. //按照工单循环
  945. foreach (var item in workOrds)
  946. {
  947. var works = workOrdMasters.Where(x => x.WorkOrd == item.Key).ToList().FirstOrDefault();
  948. if (dictInProduction.ContainsKey(works.ItemNum))
  949. {
  950. dictInProduction[works.ItemNum] += works.QtyOrded - works.QtyCompleted;
  951. }
  952. else
  953. {
  954. dictInProduction.Add(works.ItemNum, works.QtyOrded - works.QtyCompleted);
  955. }
  956. }
  957. itemNumbers.ForEach(a =>
  958. {
  959. EOPDto eOP = new EOPDto();
  960. eOP.ItemNumber = a;
  961. eOP.Qty = 0;
  962. if (dictInProduction.ContainsKey(a))
  963. eOP.Qty = dictInProduction[a];
  964. itemQty.Add(eOP);
  965. });
  966. return itemQty;
  967. }
  968. /// <summary>
  969. /// 获取物料在制数量
  970. /// </summary>
  971. /// <param name="itemNumbers"></param>
  972. /// <param name="input"></param>
  973. /// <returns></returns>
  974. public List<EOPDto> GetInProdcutQty(List<string> itemNumbers, InputDto input)
  975. {
  976. List<EOPDto> itemQty = new List<EOPDto>();
  977. DateTime startYear = new DateTime(DateTime.Now.AddYears(-1).Year, 1, 1);
  978. DateTime endYear = new DateTime(DateTime.Now.Year, 12, 31);
  979. List<WorkOrdRouting> workOrdRoutings = _workOrdRouting.Select(x => x.IsActive && x.QtyComplete > 0 && x.Domain == input.factory_id.ToString()).Where(p => p.DueDate >= startYear && p.DueDate <= endYear).ToList();
  980. decimal? InProductionQty = 0.00m;
  981. var workOrds = workOrdRoutings.GroupBy(x => x.WorkOrd).ToList();
  982. Dictionary<string, decimal> dictInProduction = new Dictionary<string, decimal>();
  983. //按照工单循环
  984. //某工单10-90工序 Max(10-80工序QtyComplete)-90工序QtyComplete =在制数量
  985. foreach (var item in workOrds)
  986. {
  987. var workOrdRoutingList = workOrdRoutings.Where(x => x.WorkOrd == item.Key).OrderByDescending(o => o.OP).ToList();
  988. //找出最大工序
  989. var MaxOp = workOrdRoutingList.FirstOrDefault();
  990. //查询出其他工序最大值
  991. var MaxQtyComplete = workOrdRoutingList.Where(x => x.RecID != MaxOp.RecID).ToList().Max(o => o.QtyComplete);
  992. InProductionQty += MaxQtyComplete - MaxOp.QtyComplete;
  993. if (dictInProduction.ContainsKey(MaxOp.ItemNum))
  994. {
  995. dictInProduction[MaxOp.ItemNum] += InProductionQty.Value;
  996. }
  997. else
  998. {
  999. dictInProduction.Add(MaxOp.ItemNum, InProductionQty.Value);
  1000. }
  1001. }
  1002. itemNumbers.ForEach(a =>
  1003. {
  1004. EOPDto eOP = new EOPDto();
  1005. eOP.ItemNumber = a;
  1006. eOP.Qty = 0;
  1007. if (dictInProduction.ContainsKey(a))
  1008. eOP.Qty = dictInProduction[a];
  1009. itemQty.Add(eOP);
  1010. });
  1011. return itemQty;
  1012. }
  1013. /// <summary>
  1014. /// 更新年度生产大纲
  1015. /// </summary>
  1016. /// <param name="input"></param>
  1017. /// <returns></returns>
  1018. /// <exception cref="NotImplementedException"></exception>
  1019. public async Task<string> DemandAnalysis(InputDto input)
  1020. {
  1021. string productResult = await SaveAnnualProductionOutline(input);
  1022. if (productResult != "OK")
  1023. return productResult;
  1024. return "OK|刷新成功!";
  1025. }
  1026. /// <summary>
  1027. /// 调整成品ROP和最高库存水位
  1028. /// </summary>
  1029. /// <param name="input"></param>
  1030. /// <returns></returns>
  1031. public async Task<string> CalcROP(InputDto input)
  1032. {
  1033. //var IsActived = _AccountValidityAppService.IsActived();
  1034. //if (!IsActived)
  1035. //{
  1036. // return "此账号已限制访问";
  1037. //}
  1038. //来自定时任务的请求
  1039. if (input.year == 0 && input.month == 0)
  1040. {
  1041. input.year = DateTime.Now.Year;
  1042. input.month = DateTime.Now.Month;
  1043. }
  1044. //1.获取补货模型全局参数
  1045. ReplenishmentDto replenishmentDto = GetROPParam(input.factory_id.ToString());
  1046. List<ReplenishmentROPWeekPlan> addList = new List<ReplenishmentROPWeekPlan>();
  1047. List<ReplenishmentROPWeekPlan> updateList = new List<ReplenishmentROPWeekPlan>();//更新上一个月的实际出库数量
  1048. //获取存货周转率设置
  1049. var turnOverlist = _ReplenishmentTurnOverSet.GetListAsync(a => a.factory_id == input.factory_id).Result;
  1050. //获取补货模型前H周期和未来F个周期的数据
  1051. List<string> planMonthList = new List<string>();
  1052. for (int j = -replenishmentDto.HistoryOutStockMonth; j < replenishmentDto.SaleFcstMonth; j++)
  1053. {
  1054. string itemMonth = $"{DateTime.Now.AddMonths(j).Year}-{DateTime.Now.AddMonths(j).Month.ToString("00")}";
  1055. planMonthList.Add(itemMonth);
  1056. }
  1057. var planList = new List<MonthlyShipmentPlan>();
  1058. foreach (var itemMonth in planMonthList)
  1059. {
  1060. var annualProductionMonth = _monthlyShipmentPlan.Select(x => itemMonth == x.PlanMonth && !x.IsDeleted && x.factory_id == input.factory_id).OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
  1061. if (annualProductionMonth != null && annualProductionMonth.Count > 0)
  1062. {
  1063. planList.AddRange(annualProductionMonth);
  1064. }
  1065. else
  1066. {
  1067. var MaxVersion = _monthlyShipmentPlanHistory.Select(a => a.factory_id == input.factory_id && !a.IsDeleted).Max(b => b.VERSION);
  1068. if (!string.IsNullOrEmpty(MaxVersion))
  1069. {
  1070. var annualProductionMonthHistory = _monthlyShipmentPlanHistory.Select(x => itemMonth == x.PlanMonth && x.VERSION == MaxVersion && !x.IsDeleted && x.factory_id == input.factory_id).OrderByDescending(v => v.VERSION).ThenBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
  1071. if (annualProductionMonthHistory != null && annualProductionMonthHistory.Count > 0)
  1072. {
  1073. var returnlist = ObjectMapper.Map<List<MonthlyShipmentPlanHistory>, List<MonthlyShipmentPlan>>(annualProductionMonthHistory);
  1074. planList.AddRange(returnlist);
  1075. }
  1076. }
  1077. }
  1078. }
  1079. planList = planList.OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
  1080. //获取BOM用于分解到原材料
  1081. var boms = _ic_bom.GetListAsync(a => planList.Select(p => p.SAPItemNumber).Distinct().ToList().Contains(a.item_number) && a.factory_id == input.factory_id).Result;
  1082. var planItemList = planList.Select(a => a.SAPItemNumber).Distinct().ToList();
  1083. var bomItemList = boms.Select(a => a.item_number).Distinct().ToList();
  1084. var expectedList = planItemList.Except(bomItemList).ToList();
  1085. if (expectedList.Count > 0)
  1086. {
  1087. throw new NotImplementedException("月度发货计划物料" + string.Join(",", expectedList) + "没有维护BOM!");
  1088. }
  1089. var pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
  1090. List<mo_ic_bom> autoCreates = new List<mo_ic_bom>();
  1091. boms.ForEach(p =>
  1092. {
  1093. if (!pretreatments.Where(s => s.sourceid == p.mysql_id).Any())
  1094. {
  1095. autoCreates.Add(p);
  1096. }
  1097. });
  1098. if (autoCreates.Any())
  1099. {
  1100. AutoCreateBomBill(input.company_id.ToString(), autoCreates);
  1101. pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
  1102. }
  1103. var mesItemList = _itemMaster.Select(a => pretreatments.Select(p => p.item_number).Contains(a.ItemNum) && a.Domain == input.factory_id.ToString() && a.IsActive);
  1104. var itemProductList = _mysql_ic_item.GetListAsync(a => pretreatments.Select(p => p.item_number).Contains(a.number) && !a.IsDeleted && a.factory_id == input.factory_id).Result;
  1105. var itemList = itemProductList.Select(a => a.number).ToList();
  1106. var srm_purchaseList = _srmPurchase.GetListAsync(a => pretreatments.Select(p => p.item_number).Contains(a.number) && !a.IsDeleted).Result;
  1107. var ropModelList = _replenishmentROPWeekPlan.GetListAsync(a => itemList.Contains(a.number) && planMonthList.Contains(a.planmonth) && a.factory_id == input.factory_id).Result;
  1108. //获取成品库存、灭菌库存、在制库存(会从SAP同步的库存表更新到LocationDetail、ic_item表中)
  1109. var locations = _invMaster.Select(p => p.Domain == input.factory_id.ToString() && itemList.Contains(p.ItemNum) && p.IsActive);
  1110. //国科海王只有成品
  1111. //var DMSItemList = _DMS_IN_ITEMMAPPING.Select(a => planList.Select(p => p.SAPItemNumber).ToList().Contains(a.CfnERPCode));
  1112. //var gkhwStock = _DMS_IN_LOCDETAIL.Select(a => (a.DealerCode == "RQ000005" || a.DealerCode == "RQ000002"));
  1113. decimal? InProductionQty = 0.00m;
  1114. //获取在制数量 获取工单数取每年4月到12月底的工单
  1115. DateTime startYear = new DateTime(DateTime.Now.Year, 1, 1);
  1116. DateTime endYear = new DateTime(DateTime.Now.Year, 12, 31);
  1117. List<WorkOrdRouting> workOrdRoutings = _workOrdRouting.Select(x => x.IsActive && x.QtyComplete > 0 && x.Domain == input.factory_id.ToString()).Where(p => p.DueDate >= startYear && p.DueDate <= endYear).ToList();
  1118. var workOrds = workOrdRoutings.GroupBy(x => x.WorkOrd).ToList();
  1119. Dictionary<string, decimal> dictItemStock = new Dictionary<string, decimal>();
  1120. //按照工单循环
  1121. //某工单10-90工序 Max(10-80工序QtyComplete)-90工序QtyComplete =在制数量
  1122. foreach (var item in workOrds)
  1123. {
  1124. var workOrdRoutingList = workOrdRoutings.Where(x => x.WorkOrd == item.Key).OrderByDescending(o => o.OP).ToList();
  1125. //找出最大工序
  1126. var MaxOp = workOrdRoutingList.FirstOrDefault();
  1127. //查询出其他工序最大值
  1128. var MaxQtyComplete = workOrdRoutingList.Where(x => x.RecID != MaxOp.RecID).ToList().Max(o => o.QtyComplete);
  1129. InProductionQty += MaxQtyComplete - MaxOp.QtyComplete;
  1130. if (dictItemStock.ContainsKey(MaxOp.ItemNum))
  1131. {
  1132. dictItemStock[MaxOp.ItemNum] += InProductionQty.Value;
  1133. }
  1134. else
  1135. {
  1136. dictItemStock.Add(MaxOp.ItemNum, InProductionQty.Value);
  1137. }
  1138. }
  1139. foreach (var item in locations)
  1140. {
  1141. //库存合计 + 在制 + 灭菌中 (InvMaster没有过滤灭菌中状态可能已经算在可用库存中了)
  1142. //5008成品线边库,8001成品合格库,8000成品待检
  1143. if (item.Location == "5008" || item.Location == "5009" || item.Location == "5010" || item.Location == "8000" || item.Location == "8001" || item.Location == "8002" || item.Location == "8003" || item.Location == "8004" || item.Location == "8005")
  1144. {
  1145. if (dictItemStock.ContainsKey(item.ItemNum))
  1146. {
  1147. dictItemStock[item.ItemNum] += (item.AvailStatusQty.GetValueOrDefault() + item.Assay.GetValueOrDefault());
  1148. }
  1149. else
  1150. {
  1151. dictItemStock.Add(item.ItemNum, (item.AvailStatusQty.GetValueOrDefault() + item.Assay.GetValueOrDefault()));
  1152. }
  1153. }
  1154. }
  1155. foreach (var item in itemList)
  1156. {
  1157. if (!dictItemStock.ContainsKey(item))
  1158. {
  1159. dictItemStock.Add(item, 0);
  1160. }
  1161. }
  1162. //取过去6个月成品发货出库记录
  1163. var dateBegin = DateTime.Now.AddMonths(-6);
  1164. var datePreBegin = DateTime.Now.AddMonths(-1);
  1165. var dateEnd = DateTime.Now;
  1166. //获取瑞奇发往国科海王的记录
  1167. var gkhwList = _ASNBOLShipperMaster.Select(a => a.Domain == input.factory_id.ToString() && (a.SoldTo == "10002080" || a.SoldTo == "10001981"));
  1168. var recidList = gkhwList.Select(a => Convert.ToInt64(a.RecID)).ToList();
  1169. //获取瑞奇发货记录
  1170. var shipList = _ASNBOLShipperDetail.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.shtype == "SH" && a.Typed != "S" && a.RealQty > 0
  1171. && itemList.Contains(a.ContainerItem) && a.ShipDate >= dateBegin && a.ShipDate <= dateEnd && !recidList.Contains(a.ASNBOLShipperRecID));//瑞奇只算瑞奇排除国科海王
  1172. //获取瑞奇上月发货记录
  1173. var shipMList = shipList.Where(a => a.ShipDate >= datePreBegin && a.ShipDate <= dateEnd).ToList();//瑞奇只算瑞奇排除国科海王
  1174. ////获取国科海王发货记录
  1175. //var gkItemList = planList.Where(p => p.DistributionChannel == "国科").Select(p => p.SAPItemNumber).ToList();
  1176. //var DMSItemListGK = _DMS_IN_ITEMMAPPING.Select(a => gkItemList.Contains(a.CfnERPCode));
  1177. //var shipListGK = _DMS_IN_SHIPPINGDETAIL.Select(a =>
  1178. //DMSItemListGK.Select(g => g.CfnCode).Contains(a.UPN) && a.ParentDealerCode == "RQ000005" && a.ShipmentDate >= DateOnly.FromDateTime(dateBegin) && a.ShipmentDate <= DateOnly.FromDateTime(dateEnd));//国科
  1179. //var hwItemList = planList.Where(p => p.DistributionChannel == "海王").Select(p => p.SAPItemNumber).ToList();
  1180. //var DMSItemListHW = _DMS_IN_ITEMMAPPING.Select(a => hwItemList.Contains(a.CfnERPCode));
  1181. //var shipListHW = _DMS_IN_SHIPPINGDETAIL.Select(a =>
  1182. //DMSItemListHW.Select(g => g.CfnCode).Contains(a.UPN) && a.ParentDealerCode == "RQ000002" && a.ShipmentDate >= DateOnly.FromDateTime(dateBegin) && a.ShipmentDate <= DateOnly.FromDateTime(dateEnd));//海王
  1183. //领料出库记录
  1184. var pickbilllist = _invTransHist.Select(a => a.Domain == input.factory_id.ToString() && a.TransType == "iss-wo" && a.IsActive && a.CreateTime >= dateBegin && itemList.Contains(a.ItemNum));
  1185. //出库记录
  1186. var invTransHists = _invTransHist.Select(a => a.Domain == input.factory_id.ToString() && a.IsActive && a.CreateTime >= dateBegin && itemList.Contains(a.ItemNum) && a.QtyChange < 0);
  1187. //对账单,取对账日期最新的数据
  1188. string sqldzd = @"SELECT ItemNum,1.0*NETPR/PEINH * (1+kbetr) as NETPR FROM (SELECT MATNR AS ItemNum,NETPR,PEINH,kbetr,ROW_NUMBER() OVER (PARTITION BY MATNR ORDER BY BUDAT DESC) AS rn FROM SupplierStatement ) as SupplierStatement WHERE rn = 1";
  1189. var supplierStatementDtos = _businessDbContext.SupplierStatementDto.FromSqlRaw(sqldzd).ToList();
  1190. List<ReplenishmentROPWeekPlanDto> replenishmentROPWeekPlanDtos = GetRopAmount(itemList.Distinct().ToList(), supplierStatementDtos, invTransHists, input);
  1191. // var gkCNCCodeList = DMSItemListGK.Select(g => g.CfnCode).ToList();
  1192. // var dateOnlyCurrent = DateOnly.FromDateTime(datePreBegin);
  1193. // var dateOnlyNow = DateOnly.FromDateTime(dateEnd);
  1194. // var shipMListGK = _DMS_IN_SHIPPINGDETAIL.Select(a =>
  1195. //gkCNCCodeList.Contains(a.UPN) && a.ParentDealerCode == "RQ000005" && a.ShipmentDate >= dateOnlyCurrent && a.ShipmentDate <= dateOnlyNow);//国科
  1196. // var hwCNCCodeList = DMSItemListHW.Select(g => g.CfnCode).ToList();
  1197. // var shipMListHW = _DMS_IN_SHIPPINGDETAIL.Select(a =>
  1198. //hwCNCCodeList.Contains(a.UPN) && a.ParentDealerCode == "RQ000002" && a.ShipmentDate >= dateOnlyCurrent && a.ShipmentDate <= dateOnlyNow);//海王
  1199. var itemGroup = shipList.GroupBy(p => p.ContainerItem)
  1200. .Select(p => new ASNBOLShipperDetail
  1201. {
  1202. QtyToShip = p.Sum(a => a.QtyToShip),
  1203. ContainerItem = p.Key
  1204. }).ToList();
  1205. var itemMGroup = shipMList.GroupBy(p => p.ContainerItem)
  1206. .Select(p => new ASNBOLShipperDetail
  1207. {
  1208. QtyToShip = p.Sum(a => a.QtyToShip),
  1209. ContainerItem = p.Key
  1210. }).ToList();
  1211. //var itemGroupGK = shipListGK.GroupBy(p => p.UPN)
  1212. // .Select(p => new ASNBOLShipperDetail
  1213. // {
  1214. // QtyToShip = p.Sum(a => a.Qty),
  1215. // ContainerItem = p.Key
  1216. // }).ToList();
  1217. //var itemMGroupGK = shipMListGK.GroupBy(p => p.UPN)
  1218. // .Select(p => new ASNBOLShipperDetail
  1219. // {
  1220. // QtyToShip = p.Sum(a => a.Qty),
  1221. // ContainerItem = p.Key
  1222. // }).ToList();
  1223. //var itemGroupHW = shipListHW.GroupBy(p => p.UPN)
  1224. // .Select(p => new ASNBOLShipperDetail
  1225. // {
  1226. // QtyToShip = p.Sum(a => a.Qty),
  1227. // ContainerItem = p.Key
  1228. // }).ToList();
  1229. //var itemMGroupHW = shipMListHW.GroupBy(p => p.UPN)
  1230. // .Select(p => new ASNBOLShipperDetail
  1231. // {
  1232. // QtyToShip = p.Sum(a => a.Qty),
  1233. // ContainerItem = p.Key
  1234. // }).ToList();
  1235. var mathtool = new MathNet.Numerics.Distributions.Normal();
  1236. //更新上个月计划发货数据为实际出库数据(先算成品,原材料后面单独计算)
  1237. Dictionary<string, decimal?> preMonthRQQty = new Dictionary<string, decimal?>();
  1238. ropModelList?.Where(r => r.year == DateTime.Now.AddMonths(-1).Year && r.month == DateTime.Now.AddMonths(-1).Month).ToList()?.ForEach
  1239. (m =>
  1240. {
  1241. //只更新成品
  1242. if (planList.Any(a => a.SAPItemNumber == m.number))
  1243. {
  1244. if (m.distributionchannel == "瑞奇")
  1245. {
  1246. if (!preMonthRQQty.ContainsKey(m.number))
  1247. {
  1248. preMonthRQQty.Add(m.number, m.plan_out_qty);
  1249. }
  1250. //成品算销售出库数量
  1251. if (itemGroup.Any(a => a.ContainerItem == m.number))
  1252. {
  1253. m.plan_out_qty = itemGroup.Find(a => a.ContainerItem == m.number)?.QtyToShip;
  1254. updateList.Add(m);
  1255. preMonthRQQty[m.number] = m.plan_out_qty;
  1256. }
  1257. }
  1258. //else if (m.distributionchannel == "国科")
  1259. //{
  1260. // if (itemGroupGK.Any(a => a.ContainerItem == m.number))
  1261. // {
  1262. // m.plan_out_qty = itemGroupGK.Find(a => a.ContainerItem == m.number)?.QtyToShip;
  1263. // updateList.Add(m);
  1264. // }
  1265. //}
  1266. //else if (m.distributionchannel == "海王")
  1267. //{
  1268. // if (itemGroupHW.Any(a => a.ContainerItem == m.number))
  1269. // {
  1270. // m.plan_out_qty = itemGroupHW.Find(a => a.ContainerItem == m.number)?.QtyToShip;
  1271. // updateList.Add(m);
  1272. // }
  1273. //}
  1274. }
  1275. });
  1276. //更新瑞奇原材料上个月出库次数(按照BOM展开合计汇总)
  1277. string planPreMonth = $"{DateTime.Now.AddMonths(-1).Year}-{DateTime.Now.AddMonths(-1).Month.ToString("00")}";
  1278. List<ReplenishmentSubItemDto> subItem = new List<ReplenishmentSubItemDto>();
  1279. planList.Where(a => a.DistributionChannel == "瑞奇" && a.PlanMonth == planPreMonth).ToList().ForEach(a =>
  1280. {
  1281. var planBOM = boms.Find(b => b.item_number == a.SAPItemNumber);
  1282. if (planBOM == null)
  1283. {
  1284. new NLogHelper("CalcROP").WriteLog("CalcROP", "CalcROP数据错误:" + a.SAPItemNumber + "不在BOM里", _currentTenant.Id.ToString());
  1285. }
  1286. else
  1287. {
  1288. var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList();
  1289. var returnlist = ObjectMapper.Map<List<b_bom_pretreatment>, List<BomChildExamineDto>>(pretreament);
  1290. returnlist = returnlist.OrderBy(s => s.num_order).ToList();
  1291. var level1Dto = returnlist[0];
  1292. if (preMonthRQQty.ContainsKey(a.SAPItemNumber))
  1293. {
  1294. level1Dto.needCount = preMonthRQQty[a.SAPItemNumber].GetValueOrDefault();
  1295. }
  1296. else
  1297. {
  1298. level1Dto.needCount = a.Qty;
  1299. }
  1300. CaclMaterialShortage(returnlist);
  1301. foreach (var item in returnlist)
  1302. {
  1303. if (item.item_number != a.SAPItemNumber)
  1304. {
  1305. if (subItem.Any(s => s.ItemNumber == item.item_number && s.PlanMonth == planPreMonth))
  1306. {
  1307. subItem.Find(s => s.ItemNumber == item.item_number && s.PlanMonth == planPreMonth).Qty += item.needCount;
  1308. }
  1309. else
  1310. {
  1311. subItem.Add(new ReplenishmentSubItemDto { ItemNumber = item.item_number, Qty = item.needCount, PlanMonth = planPreMonth });
  1312. }
  1313. }
  1314. }
  1315. }
  1316. });
  1317. ropModelList?.Where(r => r.year == DateTime.Now.AddMonths(-1).Year && r.month == DateTime.Now.AddMonths(-1).Month && r.distributionchannel == "瑞奇").ToList()?.ForEach
  1318. (m =>
  1319. {
  1320. //只更新原材料
  1321. if (!planList.Any(a => a.SAPItemNumber == m.number) && subItem.Any(s => s.ItemNumber == m.number && s.PlanMonth == planPreMonth))
  1322. {
  1323. m.plan_out_qty = subItem.Find(s => s.ItemNumber == m.number && s.PlanMonth == planPreMonth).Qty;
  1324. updateList.Add(m);
  1325. }
  1326. });
  1327. var RQShipPlanList = planList.FindAll(s => s.DistributionChannel == "瑞奇");
  1328. List<ReplenishmentSubItemDto> subItemRQList = CalcMonthPlanSubItem(RQShipPlanList, boms, pretreatments);
  1329. for (int j = 0; j < replenishmentDto.SaleFcstMonth; j++)
  1330. {
  1331. string itemMonth = $"{DateTime.Now.AddMonths(j).Year}-{DateTime.Now.AddMonths(j).Month.ToString("00")}";
  1332. //先计算成品
  1333. planList?.Where(s => s.PlanMonth == itemMonth).ToList()?.ForEach(a =>
  1334. {
  1335. var icItem = itemProductList.Find(p => p.number == a.SAPItemNumber);
  1336. if (icItem != null)
  1337. {
  1338. bool isExist = ropModelList.Find(r => r.planmonth == itemMonth && r.number == a.SAPItemNumber && r.distributionchannel == a.DistributionChannel) == null ? false : true;
  1339. var rop = new ReplenishmentROPWeekPlan();
  1340. if (isExist)
  1341. {
  1342. rop = ropModelList.Find(r => r.planmonth == itemMonth && r.number == a.SAPItemNumber && r.distributionchannel == a.DistributionChannel);
  1343. }
  1344. rop.number = a.SAPItemNumber;
  1345. rop.name = icItem.name;
  1346. rop.model = a.Model;
  1347. rop.erp_cls = icItem.erp_cls; //物料属性: 0.配置类 1.自制 2.委外加工 3.外购 4.虚拟件
  1348. rop.fversion = icItem.fversion;
  1349. rop.min_pack_qty = icItem.minpackqty;
  1350. rop.moq = icItem.moq;
  1351. rop.distributionchannel = a.DistributionChannel;
  1352. rop.lifecycle = a.LifeCycle;
  1353. rop.area = a.Area;
  1354. rop.plan_out_qty = Math.Ceiling(a.Qty);
  1355. if (planList.Where(i => i.SAPItemNumber == a.SAPItemNumber && i.DistributionChannel == a.DistributionChannel).Count() > 0)
  1356. {
  1357. rop.monthl_avg_demand = planList.Where(i => i.SAPItemNumber == a.SAPItemNumber && i.DistributionChannel == a.DistributionChannel).Average(a => a.Qty);
  1358. var nums = planList.Where(i => i.SAPItemNumber == a.SAPItemNumber && i.DistributionChannel == a.DistributionChannel).Select(a => a.Qty);
  1359. if (nums.Count() <= 1)
  1360. {
  1361. rop.monthl_avg_demand_variance = 0;
  1362. }
  1363. else
  1364. {
  1365. rop.monthl_avg_demand_variance = Math.Ceiling(Convert.ToDecimal(Math.Sqrt(nums.Sum(x => Math.Pow(Convert.ToDouble(x) - Convert.ToDouble(rop.monthl_avg_demand), 2)) / (nums.Count() - 1))));
  1366. }
  1367. }
  1368. else
  1369. {
  1370. rop.monthl_avg_demand = 0;
  1371. rop.monthl_avg_demand_variance = 0;
  1372. }
  1373. //计算月均出库
  1374. int MonthCount = 0;
  1375. decimal SumOutQty = 0;
  1376. for (int k = -1 * replenishmentDto.HistoryOutStockMonth; k < replenishmentDto.SaleFcstMonth; k++)
  1377. {
  1378. string itemMonth = $"{DateTime.Now.AddMonths(k).Year}-{DateTime.Now.AddMonths(k).Month.ToString("00")}";
  1379. if (k < 0)
  1380. {
  1381. if (ropModelList.Find(z => z.planmonth == itemMonth && z.number == a.SAPItemNumber && z.distributionchannel == a.DistributionChannel) != null)
  1382. {
  1383. SumOutQty += ropModelList.Find(z => z.planmonth == itemMonth && z.number == a.SAPItemNumber && z.distributionchannel == a.DistributionChannel).plan_out_qty.GetValueOrDefault();
  1384. MonthCount++;
  1385. }
  1386. }
  1387. else
  1388. {
  1389. if (planList.Find(z => z.PlanMonth == itemMonth && z.SAPItemNumber == a.SAPItemNumber && z.DistributionChannel == a.DistributionChannel) != null)
  1390. {
  1391. SumOutQty += planList.Find(z => z.PlanMonth == itemMonth && z.SAPItemNumber == a.SAPItemNumber && z.DistributionChannel == a.DistributionChannel).Qty;
  1392. MonthCount++;
  1393. }
  1394. }
  1395. }
  1396. if (MonthCount == 0)
  1397. {
  1398. rop.monthl_avg_outstock = 0;
  1399. }
  1400. else
  1401. {
  1402. rop.monthl_avg_outstock = Math.Ceiling(SumOutQty / MonthCount);
  1403. }
  1404. rop.year = DateTime.Now.AddMonths(j).Year;
  1405. rop.month = DateTime.Now.AddMonths(j).Month;
  1406. rop.planmonth = $"{DateTime.Now.AddMonths(j).Year}-{DateTime.Now.AddMonths(j).Month.ToString("00")}";
  1407. //供应提前期,成品取物料主数据维护的,原材料从货源清单取取不到取物料维护的
  1408. if (icItem.erp_cls == 1)
  1409. {
  1410. rop.supply_leadtime = icItem.PurLT;//默认
  1411. }
  1412. else
  1413. {
  1414. if (srm_purchaseList.Find(s => s.number == rop.number) != null)
  1415. {
  1416. rop.supply_leadtime = srm_purchaseList.Find(s => s.number == rop.number).lead_time;
  1417. }
  1418. else
  1419. {
  1420. rop.supply_leadtime = icItem.PurLT;//默认
  1421. }
  1422. }
  1423. if (rop.supply_leadtime == 0)
  1424. rop.supply_leadtime = 22;//默认
  1425. //存货周转率先取规格型号,没有再取产品系列,没有取产品线,再没有取物料配置的(主要是原材料),再没有就默认
  1426. if (turnOverlist.Find(t => t.Model == rop.model) != null)
  1427. {
  1428. rop.stock_turnover = turnOverlist.Find(t => t.Model == rop.model).RQTurnOver;
  1429. }
  1430. else if (turnOverlist.Find(t => t.ProdRange == a.ProdRange) != null)
  1431. {
  1432. rop.stock_turnover = turnOverlist.Find(t => t.ProdRange == a.ProdRange).RQTurnOver;
  1433. }
  1434. else if (turnOverlist.Find(t => t.ProdLine == a.ProdLine) != null)
  1435. {
  1436. rop.stock_turnover = turnOverlist.Find(t => t.ProdLine == a.ProdLine).RQTurnOver;
  1437. }
  1438. else if (mesItemList.Find(s => s.ItemNum == a.SAPItemNumber) != null)
  1439. {
  1440. rop.stock_turnover = mesItemList.Find(s => s.ItemNum == a.SAPItemNumber).StockTurnOver;
  1441. }
  1442. else
  1443. {
  1444. rop.stock_turnover = 4;
  1445. }
  1446. CalcFMRAndABC(rop, replenishmentDto, shipList, pickbilllist, replenishmentROPWeekPlanDtos, input);
  1447. rop.security_stock = Math.Ceiling((decimal)(mathtool.InverseCumulativeDistribution((double)rop.service_level_pct.Value) * (double)rop.monthl_avg_demand_variance));
  1448. rop.eop = Math.Ceiling(rop.monthl_avg_demand.Value * rop.supply_leadtime.Value / DateTime.DaysInMonth(DateTime.Now.AddMonths(j).Year, DateTime.Now.AddMonths(months: j).Month));
  1449. rop.rop_computed = rop.security_stock + rop.eop;
  1450. rop.max_stock_level = rop.monthl_avg_outstock * (12 / rop.stock_turnover);
  1451. //瑞奇是ROP和最高库存值两者之间取较小的值,平台是取较大的值。
  1452. if (a.DistributionChannel != "瑞奇")
  1453. {
  1454. rop.rop_revised = Math.Max(rop.rop_computed.Value, rop.max_stock_level.Value);
  1455. }
  1456. else
  1457. {
  1458. rop.rop_revised = Math.Min(rop.rop_computed.Value, rop.max_stock_level.Value);
  1459. }
  1460. //存在上一个月补货
  1461. if (updateList.Find(r => r.number == a.SAPItemNumber && r.distributionchannel == a.DistributionChannel && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}") != null)
  1462. {
  1463. var avaItem = updateList.Find(r => r.number == a.SAPItemNumber && r.distributionchannel == a.DistributionChannel && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}");
  1464. rop.avaStockQty = Math.Ceiling(avaItem.avaStockQty.GetValueOrDefault() + avaItem.montheop1.GetValueOrDefault() + avaItem.montheop2.GetValueOrDefault() - a.Qty);
  1465. }
  1466. else if (addList.Find(r => r.number == a.SAPItemNumber && r.distributionchannel == a.DistributionChannel && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}") != null)
  1467. {
  1468. var avaItem = addList.Find(r => r.number == a.SAPItemNumber && r.distributionchannel == a.DistributionChannel && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}");
  1469. rop.avaStockQty = Math.Ceiling(avaItem.avaStockQty.GetValueOrDefault() + avaItem.montheop1.GetValueOrDefault() + avaItem.montheop2.GetValueOrDefault() - a.Qty);
  1470. }
  1471. else
  1472. {
  1473. //取实际库存
  1474. //if (a.DistributionChannel == "海王")
  1475. //{
  1476. // if (DMSItemList.Find(d => d.CfnERPCode == rop.number) != null)
  1477. // {
  1478. // var itemDMS = gkhwStock.Where(o => o.UPN == DMSItemList.Find(d => d.CfnERPCode == rop.number).CfnCode && o.DealerCode == "RQ000002").ToList();
  1479. // if (itemDMS.Count > 0)
  1480. // {
  1481. // var maxDate = itemDMS.OrderByDescending(i => i.InventoryDate).First();
  1482. // rop.avaStockQty = itemDMS.Where(i => i.InventoryDate == maxDate.InventoryDate).Sum(q => q.Qty);
  1483. // }
  1484. // }
  1485. //}
  1486. //else if (a.DistributionChannel == "国科")
  1487. //{
  1488. // if (DMSItemList.Find(d => d.CfnERPCode == rop.number) != null)
  1489. // {
  1490. // var itemDMS = gkhwStock.Where(o => o.UPN == DMSItemList.Find(d => d.CfnERPCode == rop.number).CfnCode && o.DealerCode == "RQ000005").ToList();
  1491. // if (itemDMS.Count > 0)
  1492. // {
  1493. // var maxDate = itemDMS.OrderByDescending(i => i.InventoryDate).First();
  1494. // rop.avaStockQty = itemDMS.Where(i => i.InventoryDate == maxDate.InventoryDate).Sum(q => q.Qty);
  1495. // }
  1496. // }
  1497. //}
  1498. //else
  1499. //{
  1500. rop.avaStockQty = dictItemStock[a.SAPItemNumber];
  1501. //}
  1502. }
  1503. rop.montheop1 = rop.rop_computed > rop.avaStockQty.GetValueOrDefault() ? rop.eop : 0;
  1504. rop.montheop2 = rop.security_stock > rop.avaStockQty.GetValueOrDefault() ? rop.eop : 0;
  1505. rop.ProdLine = a.ProdLine;
  1506. rop.ProdRange = a.ProdRange;
  1507. rop.Languages = a.Languages;
  1508. rop.tenant_id = input.tenant_id;
  1509. rop.company_id = input.company_id;
  1510. rop.factory_id = input.factory_id;
  1511. rop.create_time = DateTime.Now;
  1512. rop.org_id = input.org_id;
  1513. if (isExist)
  1514. {
  1515. updateList.Add(rop);
  1516. }
  1517. else
  1518. {
  1519. addList.Add(rop);
  1520. }
  1521. }
  1522. });
  1523. //计算原材料
  1524. List<ReplenishmentSubItemDto> subItemRQ = subItemRQList.FindAll(a => a.PlanMonth == itemMonth);
  1525. foreach (var d in subItemRQ)
  1526. {
  1527. var icItem = itemProductList.Find(s => s.number == d.ItemNumber);
  1528. if (icItem != null && !planList.Select(r => r.SAPItemNumber).ToList().Contains(d.ItemNumber))
  1529. {
  1530. bool isExist = ropModelList.Find(r => r.planmonth == itemMonth && r.number == d.ItemNumber && r.distributionchannel == "瑞奇") == null ? false : true;
  1531. var rop = new ReplenishmentROPWeekPlan();
  1532. if (isExist)
  1533. {
  1534. rop = ropModelList.Find(r => r.planmonth == itemMonth && r.number == d.ItemNumber && r.distributionchannel == "瑞奇");
  1535. }
  1536. rop.number = d.ItemNumber;
  1537. rop.name = icItem.name;
  1538. rop.model = icItem.model;
  1539. rop.erp_cls = icItem.erp_cls; //物料属性: 0.配置类 1.自制 2.委外加工 3.外购 4.虚拟件
  1540. rop.fversion = icItem.fversion;
  1541. rop.min_pack_qty = icItem.minpackqty;
  1542. rop.moq = icItem.moq;
  1543. rop.distributionchannel = "";
  1544. rop.lifecycle = "";
  1545. rop.area = "";
  1546. rop.plan_out_qty = Math.Ceiling(d.Qty);
  1547. //月均需求用几个月的发货计划按照bom展开合计计算
  1548. CalcSubItem(subItemRQList, rop, replenishmentDto, d.ItemNumber);
  1549. //计算原材料月均出库
  1550. rop.monthl_avg_outstock = Math.Ceiling(pickbilllist.Where(z => z.ItemNum == rop.number).Sum(q => q.QtyChange.GetValueOrDefault() * -1) / 6);
  1551. rop.year = DateTime.Now.AddMonths(j).Year;
  1552. rop.month = DateTime.Now.AddMonths(j).Month;
  1553. rop.planmonth = $"{DateTime.Now.AddMonths(j).Year}-{DateTime.Now.AddMonths(j).Month.ToString("00")}";
  1554. //供应提前期,成品取物料主数据维护的,原材料从货源清单取取不到取物料维护的
  1555. if (icItem.erp_cls == 1)
  1556. {
  1557. rop.supply_leadtime = icItem.PurLT;//默认
  1558. }
  1559. else
  1560. {
  1561. if (srm_purchaseList.Find(s => s.number == rop.number) != null)
  1562. {
  1563. rop.supply_leadtime = srm_purchaseList.Find(s => s.number == rop.number).lead_time;
  1564. }
  1565. else
  1566. {
  1567. rop.supply_leadtime = icItem.PurLT;//默认
  1568. }
  1569. }
  1570. if (rop.supply_leadtime == 0)
  1571. rop.supply_leadtime = 22;//默认
  1572. //原材料周转率取物料
  1573. if (mesItemList.Find(s => s.ItemNum == rop.number) != null)
  1574. {
  1575. rop.stock_turnover = mesItemList.Find(s => s.ItemNum == rop.number).StockTurnOver;
  1576. if (rop.stock_turnover == 0)
  1577. {
  1578. rop.stock_turnover = 4;
  1579. }
  1580. }
  1581. else
  1582. {
  1583. rop.stock_turnover = 4;
  1584. }
  1585. if (rop.stock_turnover == 0)
  1586. rop.stock_turnover = 4;
  1587. CalcFMRAndABC(rop, replenishmentDto, shipList, pickbilllist, replenishmentROPWeekPlanDtos, input);
  1588. rop.security_stock = Math.Ceiling((decimal)(mathtool.InverseCumulativeDistribution((double)rop.service_level_pct.Value) * (double)rop.monthl_avg_demand_variance));
  1589. rop.eop = Math.Ceiling(rop.monthl_avg_demand.Value * rop.supply_leadtime.Value / DateTime.DaysInMonth(DateTime.Now.AddMonths(j).Year, DateTime.Now.AddMonths(j).Month));
  1590. rop.rop_computed = rop.security_stock + rop.eop;
  1591. rop.max_stock_level = rop.monthl_avg_outstock * (12 / rop.stock_turnover);
  1592. //瑞奇是ROP和最高库存值两者之间取较小的值,平台是取较大的值。
  1593. //瑞奇是ROP和最高库存值两者之间取较小的值,平台是取较大的值。
  1594. rop.rop_revised = Math.Min(rop.rop_computed.Value, rop.max_stock_level.Value);
  1595. //存在上一个月补货
  1596. if (updateList.Find(r => r.number == d.ItemNumber && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}") != null)
  1597. {
  1598. var avaItem = updateList.Find(r => r.number == d.ItemNumber && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}");
  1599. rop.avaStockQty = Math.Ceiling(avaItem.avaStockQty.GetValueOrDefault() + avaItem.montheop1.GetValueOrDefault() + avaItem.montheop2.GetValueOrDefault() - d.Qty);
  1600. }
  1601. else if (addList.Find(r => r.number == d.ItemNumber && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}") != null)
  1602. {
  1603. var avaItem = addList.Find(r => r.number == d.ItemNumber && r.planmonth == $"{DateTime.Now.AddMonths(j - 1).Year}-{DateTime.Now.AddMonths(j - 1).Month.ToString("00")}");
  1604. rop.avaStockQty = Math.Ceiling(avaItem.avaStockQty.GetValueOrDefault() + avaItem.montheop1.GetValueOrDefault() + avaItem.montheop2.GetValueOrDefault() - d.Qty);
  1605. }
  1606. else
  1607. {
  1608. //取实际库存
  1609. //1开始的库位为原料仓
  1610. rop.avaStockQty = locations.Where(a => a.ItemNum == rop.number && a.Location.StartsWith("1")).Sum(a => a.AvailStatusQty.GetValueOrDefault() + a.Assay.GetValueOrDefault());
  1611. }
  1612. rop.montheop1 = rop.rop_computed > rop.avaStockQty.GetValueOrDefault() ? rop.eop : 0;
  1613. rop.montheop2 = rop.security_stock > rop.avaStockQty.GetValueOrDefault() ? rop.eop : 0;
  1614. rop.ProdLine = "";
  1615. rop.ProdRange = "";
  1616. rop.Languages = "";
  1617. rop.tenant_id = input.tenant_id;
  1618. rop.company_id = input.company_id;
  1619. rop.factory_id = input.factory_id;
  1620. rop.create_time = DateTime.Now;
  1621. rop.org_id = input.org_id;
  1622. if (isExist)
  1623. {
  1624. updateList.Add(rop);
  1625. }
  1626. else
  1627. {
  1628. addList.Add(rop);
  1629. }
  1630. }
  1631. }
  1632. }
  1633. addList?.ForEach(item => { item.GenerateNewId(help.NextId()); });
  1634. await _businessDbContext.AddRangeAsync(addList);
  1635. _businessDbContext.UpdateRange(updateList);
  1636. await _businessDbContext.SaveChangesAsync();
  1637. return "OK";
  1638. }
  1639. private List<ReplenishmentSubItemDto> CalcMonthPlanSubItem(List<MonthlyShipmentPlan> planList, List<mo_ic_bom> boms, List<b_bom_pretreatment> pretreatments)
  1640. {
  1641. List<ReplenishmentSubItemDto> subItemRQ = new List<ReplenishmentSubItemDto>();
  1642. planList?.ForEach(r =>
  1643. {
  1644. var planBOM = boms.Find(b => b.item_number == r.SAPItemNumber);
  1645. if (planBOM == null)
  1646. {
  1647. new NLogHelper("CalcROP").WriteLog("CalcROP", "CalcROP数据错误:" + r.SAPItemNumber + "不在BOM里", _currentTenant.Id.ToString());
  1648. }
  1649. else
  1650. {
  1651. var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList();
  1652. var returnlist = ObjectMapper.Map<List<b_bom_pretreatment>, List<BomChildExamineDto>>(pretreament);
  1653. returnlist = returnlist.OrderBy(s => s.num_order).ToList();
  1654. var level1Dto = returnlist[0];
  1655. level1Dto.needCount = r.Qty;
  1656. CaclMaterialShortage(returnlist);
  1657. foreach (var item in returnlist)
  1658. {
  1659. if (item.item_number != r.SAPItemNumber)
  1660. {
  1661. var isExist = subItemRQ.Find(s => s.ItemNumber == item.item_number && s.PlanMonth == r.PlanMonth);
  1662. if (isExist != null)
  1663. {
  1664. isExist.Qty += item.needCount;
  1665. }
  1666. else
  1667. {
  1668. subItemRQ.Add(new ReplenishmentSubItemDto { ItemNumber = item.item_number, Qty = item.needCount, PlanMonth = r.PlanMonth });
  1669. }
  1670. }
  1671. }
  1672. }
  1673. });
  1674. return subItemRQ;
  1675. }
  1676. //计算原材料月均需求和方差
  1677. public void CalcSubItem(List<ReplenishmentSubItemDto> subItemRQ, ReplenishmentROPWeekPlan rop, ReplenishmentDto replenishmentDto, string ItemNum)
  1678. {
  1679. int MonthCount = 0;
  1680. decimal SumOutQty = 0;
  1681. for (int k = -1 * replenishmentDto.HistoryOutStockMonth; k < replenishmentDto.SaleFcstMonth; k++)
  1682. {
  1683. string itemMonth = $"{DateTime.Now.AddMonths(k).Year}-{DateTime.Now.AddMonths(k).Month.ToString("00")}";
  1684. if (subItemRQ.Find(z => z.PlanMonth == itemMonth && z.ItemNumber == ItemNum) != null)
  1685. {
  1686. SumOutQty += subItemRQ.Find(z => z.PlanMonth == itemMonth && z.ItemNumber == ItemNum).Qty;
  1687. MonthCount++;
  1688. }
  1689. }
  1690. decimal avaRequire = 0;
  1691. rop.monthl_avg_demand = 0;
  1692. rop.monthl_avg_demand_variance = 0;
  1693. if (MonthCount > 0)
  1694. {
  1695. avaRequire = Math.Ceiling(SumOutQty / MonthCount);
  1696. rop.monthl_avg_demand = avaRequire;
  1697. }
  1698. if (MonthCount > 1)
  1699. {
  1700. rop.monthl_avg_demand_variance = Math.Ceiling(Convert.ToDecimal(Math.Sqrt(subItemRQ.Where(w => w.ItemNumber == ItemNum).Sum(x => Math.Pow(Convert.ToDouble(x.Qty) - Convert.ToDouble(avaRequire), 2)) / (MonthCount - 1))));
  1701. }
  1702. }
  1703. /// <summary>
  1704. /// 平铺计算物料情况
  1705. /// </summary>
  1706. /// <param name="returnlist"></param>
  1707. /// <param name="item"></param>
  1708. /// <param name="count"></param>
  1709. public void CaclMaterialShortage(List<BomChildExamineDto> returnlist)
  1710. {
  1711. foreach (var item in returnlist)
  1712. {
  1713. if (item.level == 1)
  1714. {
  1715. continue;
  1716. }
  1717. //循环平铺整个资源检查的物料库存情况、缺料情况,子集缺料需要用父级缺料*子集使用数量-
  1718. var parent = returnlist.Find(s => s.fid == item.parent_id);
  1719. //当前物料总共需要数量
  1720. item.needCount = Math.Ceiling(parent.needCount * item.qty * (1 + (item.scrap.GetValueOrDefault() / 100)) + item.wastage.GetValueOrDefault());
  1721. item.needCountNoloss = parent.needCount * item.qty;
  1722. }
  1723. }
  1724. /// <summary>
  1725. /// 根据月度计划生成周计划
  1726. /// </summary>
  1727. /// <param name="input"></param>
  1728. /// <returns></returns>
  1729. public async Task<string> CalcWeekPlan(InputDto input)
  1730. {
  1731. //var IsActived = _AccountValidityAppService.IsActived();
  1732. //if (!IsActived)
  1733. //{
  1734. // return "此账号已限制访问";
  1735. //}
  1736. //1.获取补货模型全局参数
  1737. ReplenishmentDto replenishmentDto = GetROPParam(input.factory_id.ToString());
  1738. //发货计划列表,用于判断成品物料编码
  1739. //获取补货模型前H周期和未来F个周期的数据
  1740. List<string> planMonthList = new List<string>();
  1741. for (int j = -replenishmentDto.HistoryOutStockMonth; j < replenishmentDto.SaleFcstMonth + 1; j++)
  1742. {
  1743. string itemMonth = $"{DateTime.Now.AddMonths(j).Year}-{DateTime.Now.AddMonths(j).Month.ToString("00")}";
  1744. planMonthList.Add(itemMonth);
  1745. }
  1746. var shipPlanList = new List<MonthlyShipmentPlan>();
  1747. foreach (var itemMonth in planMonthList)
  1748. {
  1749. var annualProductionMonth = _monthlyShipmentPlan.Select(x => itemMonth == x.PlanMonth && !x.IsDeleted && x.factory_id == input.factory_id).OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
  1750. if (annualProductionMonth != null && annualProductionMonth.Count > 0)
  1751. {
  1752. shipPlanList.AddRange(annualProductionMonth);
  1753. }
  1754. else
  1755. {
  1756. var MaxVersion = _monthlyShipmentPlanHistory.Select(a => a.factory_id == input.factory_id && !a.IsDeleted).Max(b => b.VERSION);
  1757. if (!string.IsNullOrEmpty(MaxVersion))
  1758. {
  1759. var annualProductionMonthHistory = _monthlyShipmentPlanHistory.Select(x => itemMonth == x.PlanMonth && x.VERSION == MaxVersion && !x.IsDeleted && x.factory_id == input.factory_id).OrderByDescending(v => v.VERSION).ThenBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
  1760. if (annualProductionMonthHistory != null && annualProductionMonthHistory.Count > 0)
  1761. {
  1762. var returnlist = ObjectMapper.Map<List<MonthlyShipmentPlanHistory>, List<MonthlyShipmentPlan>>(annualProductionMonthHistory);
  1763. shipPlanList.AddRange(returnlist);
  1764. }
  1765. }
  1766. }
  1767. }
  1768. shipPlanList = shipPlanList.OrderBy(p => p.PlanMonth).ThenBy(o => o.OrderNum).ToList();
  1769. //滚动三个月12周的周计划,已经发布的周计划不改(TODO:删除未来未发布的周计划和工单(是否影响资源检查))
  1770. //最小经济批量
  1771. var weekPlanDelete = _replenishmentWeekPlan.GetListAsync(a => planMonthList.Contains(a.PlanMonth) && a.ProductionStatus != "已发布" && a.IsReplenishmentModel == "N" && a.factory_id == input.factory_id).Result;
  1772. var workOrderDelete = weekPlanDelete.Select(b => b.ProductionOrder).ToList();
  1773. _workOrdMaster.Delete(a => workOrderDelete.Contains(a.WorkOrd) && a.Domain == input.factory_id.ToString());
  1774. _workOrdRouting.Delete(a => workOrderDelete.Contains(a.WorkOrd) && a.Domain == input.factory_id.ToString());
  1775. _workOrdDetail.Delete(a => workOrderDelete.Contains(a.WorkOrd) && a.Domain == input.factory_id.ToString());
  1776. var deletedOrderList = _mysql_mes_morder.GetListAsync(a => workOrderDelete.Contains(a.morder_no) && a.factory_id == input.factory_id).Result;
  1777. var deletedIds = deletedOrderList.Select(a => a.Id).ToList();
  1778. await _mysql_mes_morder.HardDeleteAsync(deletedOrderList);
  1779. var deletedEntryList = _mysql_mes_moentry.GetListAsync(a => workOrderDelete.Contains(a.moentry_mono) && a.factory_id == input.factory_id).Result;
  1780. await _mysql_mes_moentry.HardDeleteAsync(deletedEntryList);
  1781. var examine_result = _mysql_examine_result.GetListAsync(a => workOrderDelete.Contains(a.morder_no) && a.factory_id == input.factory_id).Result;
  1782. List<srm_po_occupy> occupy = await _mysql_srm_po_occupy.GetListAsync(s => workOrderDelete.Contains(s.morder_mo));
  1783. _businessDbContext.BulkDelete(occupy);
  1784. //清理工单占用
  1785. List<mes_mooccupy> mooccupy = await _mysql_mes_mooccupy.GetListAsync(s => deletedIds.Contains(s.moo_id.GetValueOrDefault()));
  1786. if (mooccupy.Any())
  1787. {
  1788. _businessDbContext.BulkDelete(mooccupy);
  1789. }
  1790. //清理掉库存占用
  1791. var itemstockoccupy = _mysql_ic_item_stockoccupy.GetListAsync(s => workOrderDelete.Contains(s.morder_mo)).Result;
  1792. if (itemstockoccupy.Any())
  1793. {
  1794. _businessDbContext.BulkDelete(itemstockoccupy);
  1795. }
  1796. if (examine_result.Any())
  1797. {
  1798. await _mysql_bom_child_examine.HardDeleteAsync(a => examine_result.Select(b => b.Id).ToList().Contains(a.examine_id.Value) && a.factory_id == input.factory_id);
  1799. await _mysql_examine_result.HardDeleteAsync(examine_result);
  1800. }
  1801. await _replenishmentWeekPlan.HardDeleteAsync(weekPlanDelete);
  1802. //月度补货模型
  1803. var planList = _replenishmentROPWeekPlan.GetListAsync(a => planMonthList.Contains(a.planmonth) && !a.IsDeleted && a.factory_id == input.factory_id).Result;
  1804. //周补货计划
  1805. var weekPlanList = _replenishmentWeekPlan.GetListAsync(a => planMonthList.Contains(a.PlanMonth) && !a.IsDeleted && a.factory_id == input.factory_id && a.IsReplenishmentModel == "Y").Result;
  1806. //周生产计划
  1807. var weekProductPlanList = _replenishmentWeekPlan.GetListAsync(a => planMonthList.Contains(a.PlanMonth) && !a.IsDeleted && a.factory_id == input.factory_id && a.IsReplenishmentModel == "N").Result;
  1808. //发货计划物料列表
  1809. List<string> planItemList = shipPlanList?.Select(a => a.SAPItemNumber).Distinct().ToList();
  1810. var itemList = _mysql_ic_item.GetListAsync(a => planItemList.Contains(a.number) && !a.IsDeleted).Result;
  1811. var bomList = _mysql_ic_bom.GetListAsync(a => planItemList.Contains(a.item_number) && !a.IsDeleted && a.factory_id == input.factory_id).Result;
  1812. var monthPlan = _productionMasterPlan.GetListAsync(a => planItemList.Contains(a.ItemNumber) && !a.IsDeleted && a.factory_id == input.factory_id).Result;
  1813. long bang_id = help.NextId();
  1814. //获取BOM用于分解到原材料
  1815. var boms = _ic_bom.GetListAsync(a => planItemList.Contains(a.item_number) && a.factory_id == input.factory_id).Result;
  1816. var pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
  1817. List<mo_ic_bom> autoCreates = new List<mo_ic_bom>();
  1818. boms.ForEach(p =>
  1819. {
  1820. if (!pretreatments.Where(s => s.sourceid == p.mysql_id).Any())
  1821. {
  1822. autoCreates.Add(p);
  1823. }
  1824. });
  1825. if (autoCreates.Any())
  1826. {
  1827. AutoCreateBomBill(input.company_id.ToString(), autoCreates);
  1828. pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
  1829. }
  1830. routingOps = _routingOpDetail.Select(p => p.Domain == input.factory_id.ToString()).ToList();
  1831. //更新周补货计划
  1832. List<ReplenishmentWeekPlan> updateRopList = new List<ReplenishmentWeekPlan>();
  1833. List<ReplenishmentWeekPlan> addRopList = new List<ReplenishmentWeekPlan>();
  1834. //生成12周补货计划
  1835. for (int k = 0; k < 12; k++)
  1836. {
  1837. var weekPlanTime = GetNextMonday();
  1838. weekPlanTime = weekPlanTime.AddDays(7 * k);
  1839. string kMonth = $"{weekPlanTime.Year}-{weekPlanTime.Month.ToString("00")}";
  1840. //如果该10月有发布的2周生产计划,则周补货量=10月补货量-已发布的2周生产计划数量/剩余周次(2)
  1841. //周补货计划只计算成品,不需要到原材料
  1842. var monthWeekPlan = planList.Where(a => a.planmonth == kMonth && planItemList.Contains(a.number)).ToList();
  1843. foreach (var item in monthWeekPlan)
  1844. {
  1845. int publishedWeekCount = weekProductPlanList.Where(a => a.PlanMonth == kMonth && a.ItemNumber == item.number && a.ProductionStatus == "已发布" && a.DistributionChannel == item.distributionchannel).Count();
  1846. decimal publishedWeekQtySum = weekProductPlanList.Where(a => a.PlanMonth == kMonth && a.ItemNumber == item.number && a.ProductionStatus == "已发布" && a.DistributionChannel == item.distributionchannel).Sum(a => a.Qty);
  1847. var weekItemPlan = weekPlanList.Find(a => a.PlanMonth == kMonth && a.ItemNumber == item.number && a.WeekSeq == WeekOfMonth(weekPlanTime, 1) && a.DistributionChannel == item.distributionchannel);
  1848. if (publishedWeekCount < 4)
  1849. {
  1850. if (weekItemPlan != null)
  1851. {
  1852. weekItemPlan.Qty = Math.Ceiling((item.montheop1.GetValueOrDefault() + item.montheop2.GetValueOrDefault() - publishedWeekQtySum) / (4 - publishedWeekCount));
  1853. updateRopList.Add(weekItemPlan);
  1854. }
  1855. else
  1856. {
  1857. ReplenishmentWeekPlan weekItemPlanAdd = new ReplenishmentWeekPlan();
  1858. weekItemPlanAdd.Area = item.area;
  1859. weekItemPlanAdd.Week = $"WK{GetWeekOfYear(weekPlanTime).ToString("00")}";
  1860. weekItemPlanAdd.DistributionChannel = item.distributionchannel;
  1861. weekItemPlanAdd.ProdLine = item.ProdLine;
  1862. weekItemPlanAdd.ProdRange = item.ProdRange;
  1863. weekItemPlanAdd.Model = item.model;
  1864. weekItemPlanAdd.ItemNumber = item.number;
  1865. weekItemPlanAdd.Languages = item.Languages;
  1866. weekItemPlanAdd.Qty = Math.Ceiling((item.montheop1.GetValueOrDefault() + item.montheop2.GetValueOrDefault() - publishedWeekQtySum) / (4 - publishedWeekCount));
  1867. weekItemPlanAdd.Year = weekPlanTime.Year;
  1868. weekItemPlanAdd.Month = weekPlanTime.Month;
  1869. weekItemPlanAdd.PlanMonth = $"{weekPlanTime.Year}-{weekPlanTime.Month.ToString("00")}"; ;
  1870. weekItemPlanAdd.WeekSeq = WeekOfMonth(weekPlanTime, 1);
  1871. weekItemPlanAdd.tenant_id = input.tenant_id;
  1872. weekItemPlanAdd.company_id = input.company_id;
  1873. weekItemPlanAdd.factory_id = input.factory_id;
  1874. weekItemPlanAdd.create_time = DateTime.Now;
  1875. weekItemPlanAdd.org_id = input.org_id;
  1876. weekItemPlanAdd.ItemStatus = "";
  1877. weekItemPlanAdd.IsReplenishmentModel = "Y";
  1878. addRopList.Add(weekItemPlanAdd);
  1879. }
  1880. }
  1881. }
  1882. }
  1883. await _businessDbContext.AddRangeAsync(addRopList);
  1884. _businessDbContext.UpdateRange(updateRopList);
  1885. await _businessDbContext.SaveChangesAsync();
  1886. //更新周生产计划
  1887. //生产线明细表
  1888. List<ProdLineDetail> prodLines = new List<ProdLineDetail>();
  1889. List<LineMaster> lineMasters = new List<LineMaster>();
  1890. var routingOpList = _routingOpDetail.Select(x => x.Ufld1 == "组装" && x.MilestoneOp).ToList();
  1891. //生成12周计划工单
  1892. //中间件汇总,比如A成品10、11、12月都需要中间件C,B成品11、12月都需要中间件C,那么中间件C需要每个月汇总平均分到4周
  1893. Dictionary<string, decimal?> subProductItem = new Dictionary<string, decimal?>();
  1894. Dictionary<string, BomChildExamineDto> subProductItemModel = new Dictionary<string, BomChildExamineDto>();
  1895. var ropList = planList.Where(t => shipPlanList.Select(s => s.SAPItemNumber).Distinct().ToList().Contains(t.number)).Select(t => t.number).Distinct().ToList();
  1896. var itemMasterList = _itemMaster.Select(t => ropList.Contains(t.ItemNum) && t.Domain == input.factory_id.ToString());
  1897. Dictionary<string, decimal> minordsalesQty = new Dictionary<string, decimal>();
  1898. List<mes_morder> moList = new List<mes_morder>();
  1899. List<mes_moentry> moentryList = new List<mes_moentry>();
  1900. List<ReplenishmentWeekPlan> weekPlan = new List<ReplenishmentWeekPlan>();
  1901. for (int k = 0; k < 12; k++)
  1902. {
  1903. var weekTime = GetNextMonday().AddDays(28);//增加四周
  1904. weekTime = weekTime.AddDays(7 * k);
  1905. string kMonth = $"{weekTime.Year}-{weekTime.Month.ToString("00")}";
  1906. var monthWeekPlan = planList.Where(a => a.planmonth == kMonth).ToList();
  1907. foreach (var itemSeq in ropList)
  1908. {
  1909. var monthPlanItem = monthPlan.Find(x => x.ItemNumber == itemSeq);
  1910. //瑞奇国科海王
  1911. var monthPlanTotal = monthWeekPlan.Where(x => x.number == itemSeq).ToList();
  1912. if (monthPlanTotal != null && monthPlanTotal.Count > 0)
  1913. {
  1914. var item = monthPlanTotal[0];
  1915. //瑞奇补货计划!Y5 + 瑞奇补货计划!Z5 + 国科补货计划!Y5 + 国科补货计划!Z5 + 海王补货计划!Y4 + 海王补货计划!Z4
  1916. var itemQty = monthPlanTotal.Sum(a => a.montheop1) + monthPlanTotal.Sum(a => a.montheop2);
  1917. int days = 15;
  1918. if (item.area != "国内" && item.area != "中国")
  1919. {
  1920. days = 8;
  1921. }
  1922. if (itemQty <= 0)
  1923. itemQty = 0;
  1924. //四周数量合并,完工日期取第三周的时间
  1925. if (k <= 3)
  1926. {
  1927. var MonthMo = moList.Find(a => a.product_code == itemSeq && (
  1928. a.moentry_sys_etime == GetNextMonday().AddDays(28).AddDays(-days) ||
  1929. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 7).AddDays(-days) ||
  1930. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 14).AddDays(-days) ||
  1931. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 21).AddDays(-days)));
  1932. if (MonthMo != null)
  1933. {
  1934. MonthMo.morder_production_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  1935. MonthMo.need_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  1936. MonthMo.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(14).AddDays(-ProductTime(routingOps, MonthMo.product_code, input.factory_id.ToString(), MonthMo.need_number.GetValueOrDefault()) - days);
  1937. MonthMo.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(14).AddDays(-days);
  1938. moentryList.Find(a => a.moentry_mono == MonthMo.morder_no).morder_production_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  1939. moentryList.Find(a => a.moentry_mono == MonthMo.morder_no).need_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  1940. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).PlanStartDate = MonthMo.moentry_sys_stime;
  1941. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Week = $"WK{GetWeekOfYear(MonthMo.moentry_sys_stime.Value).ToString("00")}";
  1942. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Qty = MonthMo.morder_production_number.Value;
  1943. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Year = GetNextMonday().AddDays(28).AddDays(14).Year;
  1944. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Month = GetNextMonday().AddDays(28).AddDays(14).Month;
  1945. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(14), 1);
  1946. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(14).Year}-{GetNextMonday().AddDays(28).AddDays(14).Month.ToString("00")}";
  1947. if (item.area == "国内" || item.area == "中国")
  1948. {
  1949. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).SterilizationDate = MonthMo.moentry_sys_etime.Value;
  1950. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).InStockDate = MonthMo.moentry_sys_etime.Value.AddDays(days);
  1951. }
  1952. else
  1953. {
  1954. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).SterilizationDate = MonthMo.moentry_sys_etime.Value;
  1955. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).InStockDate = MonthMo.moentry_sys_etime.Value.AddDays(days);
  1956. }
  1957. }
  1958. else
  1959. {
  1960. var bom = bomList.Find(b => b.item_number == itemSeq);
  1961. var ic_item = itemList.Find(b => b.number == itemSeq);
  1962. mes_morder mes_Morder = new mes_morder();
  1963. mes_Morder.GenerateNewId(help.NextId());
  1964. mes_Morder.morder_type = MorderEnum.JhMorder;
  1965. mes_Morder.work_order_type = MorderEnum.CgMorder;
  1966. mes_Morder.morder_state = "";
  1967. mes_Morder.morder_no = Guid.NewGuid().ToString();
  1968. mes_Morder.fms_number = ic_item.fms_number;
  1969. mes_Morder.bom_number = bom.bom_number;
  1970. mes_Morder.fmodel = ic_item.model;
  1971. mes_Morder.moentry_startup_status = 0;
  1972. mes_Morder.tenant_id = input.tenant_id;
  1973. mes_Morder.factory_id = input.factory_id;
  1974. mes_Morder.company_id = input.company_id;
  1975. mes_Morder.org_id = input.org_id;
  1976. mes_Morder.product_code = ic_item.number;
  1977. mes_Morder.product_name = ic_item.name;
  1978. mes_Morder.morder_date = DateTime.Now.Date.AddDays(1);
  1979. mes_Morder.moentry_prd = null;
  1980. mes_Morder.moentry_prdname = null;
  1981. mes_Morder.moentry_wrkc = null;
  1982. mes_Morder.moentry_wrkcname = null;
  1983. mes_Morder.picking_qty = 0;
  1984. mes_Morder.unit = ic_item.unit;
  1985. mes_Morder.morder_production_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  1986. mes_Morder.need_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  1987. //成品半成品取周一为入库时间开始往前推
  1988. mes_Morder.moentry_sys_stime = weekTime.AddDays(-ProductTime(routingOps, ic_item.number, input.factory_id.ToString(), mes_Morder.need_number.GetValueOrDefault()) - days);
  1989. mes_Morder.moentry_sys_etime = weekTime.AddDays(-days);
  1990. mes_Morder.remaining_number = 0;
  1991. mes_Morder.create_time = DateTime.Now;
  1992. mes_Morder.bang_id = bang_id;
  1993. //生成工单子表数据
  1994. mes_moentry mes_Moentry = new mes_moentry();
  1995. mes_Moentry.GenerateNewId(help.NextId());
  1996. mes_Moentry.moentry_moid = mes_Morder.Id;
  1997. mes_Moentry.moentry_mono = mes_Morder.morder_no;
  1998. mes_Moentry.unit = ic_item.unit;
  1999. mes_Moentry.morder_production_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  2000. mes_Moentry.need_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  2001. mes_Moentry.remaining_number = 0;
  2002. mes_Moentry.tenant_id = input.tenant_id;
  2003. mes_Moentry.factory_id = input.factory_id;
  2004. mes_Moentry.company_id = input.company_id;
  2005. mes_Moentry.org_id = input.org_id;
  2006. mes_Moentry.create_time = DateTime.Now;
  2007. mes_Moentry.bang_id = bang_id;
  2008. ReplenishmentWeekPlan weekItem = new ReplenishmentWeekPlan();
  2009. weekItem.Priority = 1;
  2010. weekItem.Area = item.area;
  2011. weekItem.PlanStartDate = mes_Morder.moentry_sys_stime.GetValueOrDefault();
  2012. weekItem.Week = $"WK{GetWeekOfYear(mes_Morder.moentry_sys_stime.Value).ToString("00")}";
  2013. weekItem.OrderNO = Guid.NewGuid().ToString();
  2014. weekItem.ProductionOrder = mes_Morder.morder_no;
  2015. weekItem.SAPOrderNO = "";
  2016. weekItem.OrderType = "量产";
  2017. weekItem.ProductionBatch = "";
  2018. weekItem.ProductionStatus = "";
  2019. weekItem.ProdLine = item.ProdLine;
  2020. weekItem.ProdRange = item.ProdRange;
  2021. weekItem.Line = monthPlanItem?.WorkshopLine;
  2022. weekItem.ItemNumber = item.number;
  2023. weekItem.Model = item.model;
  2024. weekItem.Languages = item.Languages;
  2025. weekItem.Qty = mes_Morder.morder_production_number.Value;
  2026. weekItem.ItemStatus = "";
  2027. weekItem.PlanKittingDate = DateTime.Now;
  2028. weekItem.Year = weekTime.Year;
  2029. weekItem.Month = weekTime.Month;
  2030. weekItem.WeekSeq = WeekOfMonth(weekTime, 1);
  2031. weekItem.PlanMonth = kMonth;
  2032. weekItem.tenant_id = input.tenant_id;
  2033. weekItem.factory_id = input.factory_id;
  2034. weekItem.company_id = input.company_id;
  2035. weekItem.org_id = input.org_id;
  2036. weekItem.create_time = DateTime.Now;
  2037. weekItem.DistributionChannel = item.distributionchannel;
  2038. weekItem.IsReplenishmentModel = "N";
  2039. if (item.area == "国内" || item.area == "中国")
  2040. {
  2041. weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value;
  2042. weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value.AddDays(days);
  2043. }
  2044. else
  2045. {
  2046. weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value;
  2047. weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value.AddDays(days);
  2048. }
  2049. weekItem.AssembleHours = 0;
  2050. weekItem.HeatSealHours = 0;
  2051. weekItem.PackageHours = 0;
  2052. weekItem.TotalHours = 0;
  2053. //Q2023/11/15的需求同一周有相同物料的工单不继续生成,不考虑数量的偏差
  2054. if (!weekProductPlanList.Any(a => a.ItemNumber == item.number && a.Week == weekItem.Week))
  2055. {
  2056. weekPlan.Add(weekItem);
  2057. moList.Add(mes_Morder);
  2058. moentryList.Add(mes_Moentry);
  2059. }
  2060. }
  2061. if (k == 3)
  2062. {
  2063. var MonthMoTotal = moList.Find(a => a.product_code == itemSeq && (
  2064. a.moentry_sys_etime == GetNextMonday().AddDays(28).AddDays(-days) ||
  2065. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 7).AddDays(-days) ||
  2066. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 14).AddDays(-days) ||
  2067. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 21).AddDays(-days)));
  2068. if (MonthMoTotal != null)
  2069. {
  2070. if (MonthMoTotal.need_number > 0)
  2071. {
  2072. var itemMaster = itemMasterList.Find(i => i.ItemNum == itemSeq);
  2073. if (itemMaster != null && itemMaster.MinOrd > 0)
  2074. {
  2075. //考虑生产批量的计算逻辑
  2076. decimal productQty;
  2077. bool exist = minordsalesQty.TryGetValue(itemSeq, out productQty);
  2078. if (exist)
  2079. {
  2080. //不需要生产
  2081. if (MonthMoTotal.need_number <= productQty)
  2082. {
  2083. minordsalesQty[itemSeq] -= MonthMoTotal.need_number.GetValueOrDefault();
  2084. moList.Remove(MonthMoTotal);
  2085. moentryList.RemoveAll(a => a.moentry_mono == MonthMoTotal.morder_no);
  2086. weekPlan.RemoveAll(a => a.ProductionOrder == MonthMoTotal.morder_no);
  2087. }
  2088. else
  2089. {
  2090. //需要生产但是小于生产批量按生产批量生产,大于生产批量不需要改动
  2091. if (MonthMoTotal.need_number - productQty < itemMaster.MinOrd)
  2092. {
  2093. decimal needProductQty = MonthMoTotal.need_number.GetValueOrDefault() - productQty;
  2094. minordsalesQty[itemSeq] = Math.Ceiling(itemMaster.MinOrd) - needProductQty;
  2095. MonthMoTotal.morder_production_number = Math.Ceiling(itemMaster.MinOrd);
  2096. MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd);
  2097. MonthMoTotal.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(14).AddDays(-ProductTime(routingOps, MonthMoTotal.product_code, input.factory_id.ToString(), MonthMoTotal.need_number.GetValueOrDefault()) - days);
  2098. MonthMoTotal.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(14).AddDays(-days);
  2099. moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).morder_production_number = Math.Ceiling(itemMaster.MinOrd);
  2100. moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).need_number = Math.Ceiling(itemMaster.MinOrd);
  2101. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanStartDate = MonthMoTotal.moentry_sys_stime;
  2102. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Week = $"WK{GetWeekOfYear(MonthMoTotal.moentry_sys_stime.Value).ToString("00")}";
  2103. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Qty = MonthMoTotal.morder_production_number.Value;
  2104. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Year = GetNextMonday().AddDays(28).AddDays(14).Year;
  2105. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Month = GetNextMonday().AddDays(28).AddDays(14).Month;
  2106. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(14), 1);
  2107. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(14).Year}-{GetNextMonday().AddDays(28).AddDays(14).Month.ToString("00")}";
  2108. if (item.area == "国内" || item.area == "中国")
  2109. {
  2110. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value;
  2111. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days);
  2112. }
  2113. else
  2114. {
  2115. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value;
  2116. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days);
  2117. }
  2118. }
  2119. }
  2120. }
  2121. else
  2122. {
  2123. if (MonthMoTotal.need_number < Math.Ceiling(itemMaster.MinOrd))
  2124. {
  2125. minordsalesQty[itemSeq] = Math.Ceiling(itemMaster.MinOrd) - MonthMoTotal.need_number.Value;
  2126. MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd);
  2127. MonthMoTotal.morder_production_number = Math.Ceiling(itemMaster.MinOrd);
  2128. MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd);
  2129. MonthMoTotal.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(14).AddDays(-ProductTime(routingOps, MonthMoTotal.product_code, input.factory_id.ToString(), MonthMoTotal.need_number.GetValueOrDefault()) - days);
  2130. MonthMoTotal.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(14).AddDays(-days);
  2131. moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).morder_production_number = Math.Ceiling(itemMaster.MinOrd);
  2132. moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).need_number = Math.Ceiling(itemMaster.MinOrd);
  2133. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanStartDate = MonthMoTotal.moentry_sys_stime;
  2134. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Week = $"WK{GetWeekOfYear(MonthMoTotal.moentry_sys_stime.Value).ToString("00")}";
  2135. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Qty = MonthMoTotal.morder_production_number.Value;
  2136. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Year = GetNextMonday().AddDays(28).AddDays(14).Year;
  2137. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Month = GetNextMonday().AddDays(28).AddDays(14).Month;
  2138. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(14), 1);
  2139. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(14).Year}-{GetNextMonday().AddDays(28).AddDays(14).Month.ToString("00")}";
  2140. if (item.area == "国内" || item.area == "中国")
  2141. {
  2142. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value;
  2143. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days);
  2144. }
  2145. else
  2146. {
  2147. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value;
  2148. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days);
  2149. }
  2150. }
  2151. }
  2152. var planBOM = boms.Find(b => b.item_number == itemSeq);
  2153. var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList();
  2154. var returnlist = ObjectMapper.Map<List<b_bom_pretreatment>, List<BomChildExamineDto>>(pretreament);
  2155. returnlist = returnlist.OrderBy(s => s.num_order).ToList();
  2156. var level1Dto = returnlist[0];
  2157. level1Dto.needCount = MonthMoTotal.need_number.GetValueOrDefault();
  2158. CaclMaterialShortage(returnlist);
  2159. foreach (var r in returnlist)
  2160. {
  2161. if (r.item_number != itemSeq && r.erp_cls == 1 && !string.IsNullOrEmpty(r.bom_number))
  2162. {
  2163. if (subProductItem.ContainsKey(r.item_number))
  2164. {
  2165. subProductItem[r.item_number] += r.needCount;
  2166. }
  2167. else
  2168. {
  2169. subProductItem.Add(r.item_number, r.needCount);
  2170. subProductItemModel.Add(r.item_number, r);
  2171. }
  2172. }
  2173. }
  2174. }
  2175. else
  2176. {
  2177. var planBOM = boms.Find(b => b.item_number == itemSeq);
  2178. var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList();
  2179. var returnlist = ObjectMapper.Map<List<b_bom_pretreatment>, List<BomChildExamineDto>>(pretreament);
  2180. returnlist = returnlist.OrderBy(s => s.num_order).ToList();
  2181. var level1Dto = returnlist[0];
  2182. level1Dto.needCount = MonthMoTotal.need_number.GetValueOrDefault();
  2183. CaclMaterialShortage(returnlist);
  2184. foreach (var r in returnlist)
  2185. {
  2186. if (r.item_number != itemSeq && r.erp_cls == 1 && !string.IsNullOrEmpty(r.bom_number))
  2187. {
  2188. if (subProductItem.ContainsKey(r.item_number))
  2189. {
  2190. subProductItem[r.item_number] += r.needCount;
  2191. }
  2192. else
  2193. {
  2194. subProductItem.Add(r.item_number, r.needCount);
  2195. subProductItemModel.Add(r.item_number, r);
  2196. }
  2197. }
  2198. }
  2199. }
  2200. }
  2201. else
  2202. {
  2203. moList.Remove(MonthMoTotal);
  2204. moentryList.RemoveAll(a => a.moentry_mono == MonthMoTotal.morder_no);
  2205. weekPlan.RemoveAll(a => a.ProductionOrder == MonthMoTotal.morder_no);
  2206. }
  2207. }
  2208. }
  2209. }
  2210. else if (k <= 7)
  2211. {
  2212. var MonthMo = moList.Find(a => a.product_code == itemSeq && (
  2213. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 28).AddDays(-days) ||
  2214. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 35).AddDays(-days) ||
  2215. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 42).AddDays(-days) ||
  2216. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 49).AddDays(-days)));
  2217. if (MonthMo != null)
  2218. {
  2219. MonthMo.morder_production_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  2220. MonthMo.need_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  2221. MonthMo.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(42).AddDays(-ProductTime(routingOps, MonthMo.product_code, input.factory_id.ToString(), MonthMo.need_number.GetValueOrDefault()) - days);
  2222. MonthMo.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(42).AddDays(-days);
  2223. moentryList.Find(a => a.moentry_mono == MonthMo.morder_no).morder_production_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  2224. moentryList.Find(a => a.moentry_mono == MonthMo.morder_no).need_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  2225. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).PlanStartDate = MonthMo.moentry_sys_stime;
  2226. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Week = $"WK{GetWeekOfYear(MonthMo.moentry_sys_stime.Value).ToString("00")}";
  2227. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Qty = MonthMo.morder_production_number.Value;
  2228. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Year = GetNextMonday().AddDays(28).AddDays(42).Year;
  2229. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Month = GetNextMonday().AddDays(28).AddDays(42).Month;
  2230. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(42), 1);
  2231. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(42).Year}-{GetNextMonday().AddDays(28).AddDays(42).Month.ToString("00")}";
  2232. if (item.area == "国内" || item.area == "中国")
  2233. {
  2234. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).SterilizationDate = MonthMo.moentry_sys_etime.Value;
  2235. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).InStockDate = MonthMo.moentry_sys_etime.Value.AddDays(days);
  2236. }
  2237. else
  2238. {
  2239. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).SterilizationDate = MonthMo.moentry_sys_etime.Value;
  2240. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).InStockDate = MonthMo.moentry_sys_etime.Value.AddDays(days);
  2241. }
  2242. var planBOM = boms.Find(b => b.item_number == itemSeq);
  2243. var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList();
  2244. var returnlist = ObjectMapper.Map<List<b_bom_pretreatment>, List<BomChildExamineDto>>(pretreament);
  2245. returnlist = returnlist.OrderBy(s => s.num_order).ToList();
  2246. var level1Dto = returnlist[0];
  2247. level1Dto.needCount = Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  2248. CaclMaterialShortage(returnlist);
  2249. foreach (var r in returnlist)
  2250. {
  2251. if (r.item_number != itemSeq && r.erp_cls == 1 && !string.IsNullOrEmpty(r.bom_number))
  2252. {
  2253. if (subProductItem.ContainsKey(r.item_number))
  2254. {
  2255. subProductItem[r.item_number] += r.needCount;
  2256. }
  2257. else
  2258. {
  2259. subProductItem.Add(r.item_number, r.needCount);
  2260. subProductItemModel.Add(r.item_number, r);
  2261. }
  2262. }
  2263. }
  2264. }
  2265. else
  2266. {
  2267. var bom = bomList.Find(b => b.item_number == itemSeq);
  2268. var ic_item = itemList.Find(b => b.number == itemSeq);
  2269. mes_morder mes_Morder = new mes_morder();
  2270. mes_Morder.GenerateNewId(help.NextId());
  2271. mes_Morder.morder_type = MorderEnum.JhMorder;
  2272. mes_Morder.work_order_type = MorderEnum.CgMorder;
  2273. mes_Morder.morder_state = "";
  2274. mes_Morder.morder_no = Guid.NewGuid().ToString();
  2275. mes_Morder.fms_number = ic_item.fms_number;
  2276. mes_Morder.bom_number = bom.bom_number;
  2277. mes_Morder.fmodel = ic_item.model;
  2278. mes_Morder.moentry_startup_status = 0;
  2279. mes_Morder.tenant_id = input.tenant_id;
  2280. mes_Morder.factory_id = input.factory_id;
  2281. mes_Morder.company_id = input.company_id;
  2282. mes_Morder.org_id = input.org_id;
  2283. mes_Morder.product_code = ic_item.number;
  2284. mes_Morder.product_name = ic_item.name;
  2285. mes_Morder.morder_date = DateTime.Now.Date.AddDays(1);
  2286. mes_Morder.moentry_prd = null;
  2287. mes_Morder.moentry_prdname = null;
  2288. mes_Morder.moentry_wrkc = null;
  2289. mes_Morder.moentry_wrkcname = null;
  2290. mes_Morder.picking_qty = 0;
  2291. mes_Morder.unit = ic_item.unit;
  2292. mes_Morder.morder_production_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  2293. mes_Morder.need_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  2294. //成品半成品取周一为入库时间开始往前推
  2295. mes_Morder.moentry_sys_stime = weekTime.AddDays(-ProductTime(routingOps, ic_item.number, input.factory_id.ToString(), mes_Morder.need_number.GetValueOrDefault()) - days);
  2296. mes_Morder.moentry_sys_etime = weekTime.AddDays(-days);
  2297. mes_Morder.remaining_number = 0;
  2298. mes_Morder.create_time = DateTime.Now;
  2299. mes_Morder.bang_id = bang_id;
  2300. //生成工单子表数据
  2301. mes_moentry mes_Moentry = new mes_moentry();
  2302. mes_Moentry.GenerateNewId(help.NextId());
  2303. mes_Moentry.moentry_moid = mes_Morder.Id;
  2304. mes_Moentry.moentry_mono = mes_Morder.morder_no;
  2305. mes_Moentry.unit = ic_item.unit;
  2306. mes_Moentry.morder_production_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); ;
  2307. mes_Moentry.need_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); ;
  2308. mes_Moentry.remaining_number = 0;
  2309. mes_Moentry.tenant_id = input.tenant_id;
  2310. mes_Moentry.factory_id = input.factory_id;
  2311. mes_Moentry.company_id = input.company_id;
  2312. mes_Moentry.org_id = input.org_id;
  2313. mes_Moentry.create_time = DateTime.Now;
  2314. mes_Moentry.bang_id = bang_id;
  2315. ReplenishmentWeekPlan weekItem = new ReplenishmentWeekPlan();
  2316. weekItem.Priority = 1;
  2317. weekItem.Area = item.area;
  2318. weekItem.PlanStartDate = mes_Morder.moentry_sys_stime.GetValueOrDefault();
  2319. weekItem.Week = $"WK{GetWeekOfYear(mes_Morder.moentry_sys_stime.Value).ToString("00")}";
  2320. weekItem.OrderNO = Guid.NewGuid().ToString();
  2321. weekItem.ProductionOrder = mes_Morder.morder_no;
  2322. weekItem.SAPOrderNO = "";
  2323. weekItem.OrderType = "量产";
  2324. weekItem.ProductionBatch = "";
  2325. weekItem.ProductionStatus = "";
  2326. weekItem.ProdLine = item.ProdLine;
  2327. weekItem.ProdRange = item.ProdRange;
  2328. weekItem.Line = monthPlanItem?.WorkshopLine;
  2329. weekItem.ItemNumber = item.number;
  2330. weekItem.Model = item.model;
  2331. weekItem.Languages = item.Languages;
  2332. weekItem.Qty = mes_Morder.morder_production_number.Value;
  2333. weekItem.ItemStatus = "";
  2334. weekItem.PlanKittingDate = DateTime.Now;
  2335. weekItem.Year = weekTime.Year;
  2336. weekItem.Month = weekTime.Month;
  2337. weekItem.WeekSeq = WeekOfMonth(weekTime, 1);
  2338. weekItem.PlanMonth = kMonth;
  2339. weekItem.tenant_id = input.tenant_id;
  2340. weekItem.factory_id = input.factory_id;
  2341. weekItem.company_id = input.company_id;
  2342. weekItem.org_id = input.org_id;
  2343. weekItem.create_time = DateTime.Now;
  2344. weekItem.DistributionChannel = item.distributionchannel;
  2345. weekItem.IsReplenishmentModel = "N";
  2346. if (item.area == "国内" || item.area == "中国")
  2347. {
  2348. weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value;
  2349. weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value.AddDays(days);
  2350. }
  2351. else
  2352. {
  2353. weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value;
  2354. weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value.AddDays(days);
  2355. }
  2356. weekItem.AssembleHours = 0;
  2357. weekItem.HeatSealHours = 0;
  2358. weekItem.PackageHours = 0;
  2359. weekItem.TotalHours = 0;
  2360. //Q2023/11/15的需求同一周有相同物料的工单不继续生成,不考虑数量的偏差
  2361. if (!weekProductPlanList.Any(a => a.ItemNumber == item.number && a.Week == weekItem.Week))
  2362. {
  2363. weekPlan.Add(weekItem);
  2364. moList.Add(mes_Morder);
  2365. moentryList.Add(mes_Moentry);
  2366. }
  2367. }
  2368. if (k == 7)
  2369. {
  2370. var MonthMoTotal = moList.Find(a => a.product_code == itemSeq && (
  2371. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 28).AddDays(-days) ||
  2372. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 35).AddDays(-days) ||
  2373. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 42).AddDays(-days) ||
  2374. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 49).AddDays(-days)));
  2375. if (MonthMoTotal != null)
  2376. {
  2377. if (MonthMoTotal.need_number > 0)
  2378. {
  2379. var itemMaster = itemMasterList.Find(i => i.ItemNum == itemSeq);
  2380. if (itemMaster != null && itemMaster.MinOrd > 0)
  2381. {
  2382. //考虑生产批量的计算逻辑
  2383. decimal productQty;
  2384. bool exist = minordsalesQty.TryGetValue(itemSeq, out productQty);
  2385. if (exist)
  2386. {
  2387. //不需要生产
  2388. if (MonthMoTotal.need_number <= productQty)
  2389. {
  2390. minordsalesQty[itemSeq] -= MonthMoTotal.need_number.GetValueOrDefault();
  2391. moList.Remove(MonthMoTotal);
  2392. moentryList.RemoveAll(a => a.moentry_mono == MonthMoTotal.morder_no);
  2393. weekPlan.RemoveAll(a => a.ProductionOrder == MonthMoTotal.morder_no);
  2394. }
  2395. else
  2396. {
  2397. //需要生产但是小于生产批量按生产批量生产,大于生产批量不需要改动
  2398. if (MonthMoTotal.need_number - productQty < itemMaster.MinOrd)
  2399. {
  2400. decimal needProductQty = MonthMoTotal.need_number.GetValueOrDefault() - productQty;
  2401. minordsalesQty[itemSeq] = Math.Ceiling(itemMaster.MinOrd) - needProductQty;
  2402. MonthMoTotal.morder_production_number = Math.Ceiling(itemMaster.MinOrd);
  2403. MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd);
  2404. MonthMoTotal.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(42).AddDays(-ProductTime(routingOps, MonthMoTotal.product_code, input.factory_id.ToString(), MonthMoTotal.need_number.GetValueOrDefault()) - days);
  2405. MonthMoTotal.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(42).AddDays(-days);
  2406. moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).morder_production_number = Math.Ceiling(itemMaster.MinOrd);
  2407. moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).need_number = Math.Ceiling(itemMaster.MinOrd);
  2408. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanStartDate = MonthMoTotal.moentry_sys_stime;
  2409. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Week = $"WK{GetWeekOfYear(MonthMoTotal.moentry_sys_stime.Value).ToString("00")}";
  2410. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Qty = MonthMoTotal.morder_production_number.Value;
  2411. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Year = GetNextMonday().AddDays(28).AddDays(42).Year;
  2412. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Month = GetNextMonday().AddDays(28).AddDays(42).Month;
  2413. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(42), 1);
  2414. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(42).Year}-{GetNextMonday().AddDays(28).AddDays(42).Month.ToString("00")}";
  2415. if (item.area == "国内" || item.area == "中国")
  2416. {
  2417. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value;
  2418. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days);
  2419. }
  2420. else
  2421. {
  2422. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value;
  2423. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days);
  2424. }
  2425. }
  2426. }
  2427. }
  2428. else
  2429. {
  2430. if (MonthMoTotal.need_number < Math.Ceiling(itemMaster.MinOrd))
  2431. {
  2432. minordsalesQty[itemSeq] = Math.Ceiling(itemMaster.MinOrd) - MonthMoTotal.need_number.Value;
  2433. MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd);
  2434. MonthMoTotal.morder_production_number = Math.Ceiling(itemMaster.MinOrd);
  2435. MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd);
  2436. MonthMoTotal.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(42).AddDays(-ProductTime(routingOps, MonthMoTotal.product_code, input.factory_id.ToString(), MonthMoTotal.need_number.GetValueOrDefault()) - days);
  2437. MonthMoTotal.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(42).AddDays(-days);
  2438. moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).morder_production_number = Math.Ceiling(itemMaster.MinOrd);
  2439. moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).need_number = Math.Ceiling(itemMaster.MinOrd);
  2440. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanStartDate = MonthMoTotal.moentry_sys_stime;
  2441. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Week = $"WK{GetWeekOfYear(MonthMoTotal.moentry_sys_stime.Value).ToString("00")}";
  2442. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Qty = MonthMoTotal.morder_production_number.Value;
  2443. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Year = GetNextMonday().AddDays(28).AddDays(42).Year;
  2444. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Month = GetNextMonday().AddDays(28).AddDays(42).Month;
  2445. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(42), 1);
  2446. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(42).Year}-{GetNextMonday().AddDays(28).AddDays(42).Month.ToString("00")}";
  2447. if (item.area == "国内" || item.area == "中国")
  2448. {
  2449. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value;
  2450. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days);
  2451. }
  2452. else
  2453. {
  2454. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value;
  2455. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days);
  2456. }
  2457. }
  2458. }
  2459. var planBOM = boms.Find(b => b.item_number == itemSeq);
  2460. var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList();
  2461. var returnlist = ObjectMapper.Map<List<b_bom_pretreatment>, List<BomChildExamineDto>>(pretreament);
  2462. returnlist = returnlist.OrderBy(s => s.num_order).ToList();
  2463. var level1Dto = returnlist[0];
  2464. level1Dto.needCount = MonthMoTotal.need_number.GetValueOrDefault();
  2465. CaclMaterialShortage(returnlist);
  2466. foreach (var r in returnlist)
  2467. {
  2468. if (r.item_number != itemSeq && r.erp_cls == 1 && !string.IsNullOrEmpty(r.bom_number))
  2469. {
  2470. if (subProductItem.ContainsKey(r.item_number))
  2471. {
  2472. subProductItem[r.item_number] += r.needCount;
  2473. }
  2474. else
  2475. {
  2476. subProductItem.Add(r.item_number, r.needCount);
  2477. subProductItemModel.Add(r.item_number, r);
  2478. }
  2479. }
  2480. }
  2481. }
  2482. else
  2483. {
  2484. var planBOM = boms.Find(b => b.item_number == itemSeq);
  2485. var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList();
  2486. var returnlist = ObjectMapper.Map<List<b_bom_pretreatment>, List<BomChildExamineDto>>(pretreament);
  2487. returnlist = returnlist.OrderBy(s => s.num_order).ToList();
  2488. var level1Dto = returnlist[0];
  2489. level1Dto.needCount = MonthMoTotal.need_number.GetValueOrDefault();
  2490. CaclMaterialShortage(returnlist);
  2491. foreach (var r in returnlist)
  2492. {
  2493. if (r.item_number != itemSeq && r.erp_cls == 1 && !string.IsNullOrEmpty(r.bom_number))
  2494. {
  2495. if (subProductItem.ContainsKey(r.item_number))
  2496. {
  2497. subProductItem[r.item_number] += r.needCount;
  2498. }
  2499. else
  2500. {
  2501. subProductItem.Add(r.item_number, r.needCount);
  2502. subProductItemModel.Add(r.item_number, r);
  2503. }
  2504. }
  2505. }
  2506. }
  2507. }
  2508. else
  2509. {
  2510. moList.Remove(MonthMoTotal);
  2511. moentryList.RemoveAll(a => a.moentry_mono == MonthMoTotal.morder_no);
  2512. weekPlan.RemoveAll(a => a.ProductionOrder == MonthMoTotal.morder_no);
  2513. }
  2514. }
  2515. }
  2516. }
  2517. else
  2518. {
  2519. var MonthMo = moList.Find(a => a.product_code == itemSeq && (
  2520. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 56).AddDays(-days) ||
  2521. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 63).AddDays(-days) ||
  2522. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 70).AddDays(-days) ||
  2523. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 77).AddDays(-days)));
  2524. if (MonthMo != null)
  2525. {
  2526. MonthMo.morder_production_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  2527. MonthMo.need_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  2528. MonthMo.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(70).AddDays(-ProductTime(routingOps, MonthMo.product_code, input.factory_id.ToString(), MonthMo.need_number.GetValueOrDefault()) - days);
  2529. MonthMo.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(70).AddDays(-days);
  2530. moentryList.Find(a => a.moentry_mono == MonthMo.morder_no).morder_production_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  2531. moentryList.Find(a => a.moentry_mono == MonthMo.morder_no).need_number += Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  2532. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).PlanStartDate = MonthMo.moentry_sys_stime;
  2533. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Week = $"WK{GetWeekOfYear(MonthMo.moentry_sys_stime.Value).ToString("00")}";
  2534. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Qty = MonthMo.morder_production_number.Value;
  2535. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Year = GetNextMonday().AddDays(28).AddDays(70).Year;
  2536. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).Month = GetNextMonday().AddDays(28).AddDays(70).Month;
  2537. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(70), 1);
  2538. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(70).Year}-{GetNextMonday().AddDays(28).AddDays(70).Month.ToString("00")}";
  2539. if (item.area == "国内" || item.area == "中国")
  2540. {
  2541. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).SterilizationDate = MonthMo.moentry_sys_etime.Value;
  2542. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).InStockDate = MonthMo.moentry_sys_etime.Value.AddDays(days);
  2543. }
  2544. else
  2545. {
  2546. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).SterilizationDate = MonthMo.moentry_sys_etime.Value;
  2547. weekPlan.Find(a => a.ProductionOrder == MonthMo.morder_no).InStockDate = MonthMo.moentry_sys_etime.Value.AddDays(days);
  2548. }
  2549. }
  2550. else
  2551. {
  2552. var bom = bomList.Find(b => b.item_number == itemSeq);
  2553. var ic_item = itemList.Find(b => b.number == itemSeq);
  2554. mes_morder mes_Morder = new mes_morder();
  2555. mes_Morder.GenerateNewId(help.NextId());
  2556. mes_Morder.morder_type = MorderEnum.JhMorder;
  2557. mes_Morder.work_order_type = MorderEnum.CgMorder;
  2558. mes_Morder.morder_state = "";
  2559. mes_Morder.morder_no = Guid.NewGuid().ToString();
  2560. mes_Morder.fms_number = ic_item.fms_number;
  2561. mes_Morder.bom_number = bom.bom_number;
  2562. mes_Morder.fmodel = ic_item.model;
  2563. mes_Morder.moentry_startup_status = 0;
  2564. mes_Morder.tenant_id = input.tenant_id;
  2565. mes_Morder.factory_id = input.factory_id;
  2566. mes_Morder.company_id = input.company_id;
  2567. mes_Morder.org_id = input.org_id;
  2568. mes_Morder.product_code = ic_item.number;
  2569. mes_Morder.product_name = ic_item.name;
  2570. mes_Morder.morder_date = DateTime.Now.Date.AddDays(1);
  2571. mes_Morder.moentry_prd = null;
  2572. mes_Morder.moentry_prdname = null;
  2573. mes_Morder.moentry_wrkc = null;
  2574. mes_Morder.moentry_wrkcname = null;
  2575. mes_Morder.picking_qty = 0;
  2576. mes_Morder.unit = ic_item.unit;
  2577. mes_Morder.morder_production_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  2578. mes_Morder.need_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  2579. //成品半成品取周一为入库时间开始往前推
  2580. mes_Morder.moentry_sys_stime = weekTime.AddDays(-ProductTime(routingOps, ic_item.number, input.factory_id.ToString(), mes_Morder.need_number.GetValueOrDefault()) - days);
  2581. mes_Morder.moentry_sys_etime = weekTime.AddDays(-days);
  2582. mes_Morder.remaining_number = 0;
  2583. mes_Morder.create_time = DateTime.Now;
  2584. mes_Morder.bang_id = bang_id;
  2585. //生成工单子表数据
  2586. mes_moentry mes_Moentry = new mes_moentry();
  2587. mes_Moentry.GenerateNewId(help.NextId());
  2588. mes_Moentry.moentry_moid = mes_Morder.Id;
  2589. mes_Moentry.moentry_mono = mes_Morder.morder_no;
  2590. mes_Moentry.unit = ic_item.unit;
  2591. mes_Moentry.morder_production_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); ;
  2592. mes_Moentry.need_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); ;
  2593. mes_Moentry.remaining_number = 0;
  2594. mes_Moentry.tenant_id = input.tenant_id;
  2595. mes_Moentry.factory_id = input.factory_id;
  2596. mes_Moentry.company_id = input.company_id;
  2597. mes_Moentry.org_id = input.org_id;
  2598. mes_Moentry.create_time = DateTime.Now;
  2599. mes_Moentry.bang_id = bang_id;
  2600. ReplenishmentWeekPlan weekItem = new ReplenishmentWeekPlan();
  2601. weekItem.Priority = 1;
  2602. weekItem.Area = item.area;
  2603. weekItem.PlanStartDate = mes_Morder.moentry_sys_stime.GetValueOrDefault();
  2604. weekItem.Week = $"WK{GetWeekOfYear(mes_Morder.moentry_sys_stime.Value).ToString("00")}";
  2605. weekItem.OrderNO = Guid.NewGuid().ToString();
  2606. weekItem.ProductionOrder = mes_Morder.morder_no;
  2607. weekItem.SAPOrderNO = "";
  2608. weekItem.OrderType = "量产";
  2609. weekItem.ProductionBatch = "";
  2610. weekItem.ProductionStatus = "";
  2611. weekItem.ProdLine = item.ProdLine;
  2612. weekItem.ProdRange = item.ProdRange;
  2613. weekItem.Line = monthPlanItem?.WorkshopLine;
  2614. weekItem.ItemNumber = item.number;
  2615. weekItem.Model = item.model;
  2616. weekItem.Languages = item.Languages;
  2617. weekItem.Qty = mes_Morder.morder_production_number.Value;
  2618. weekItem.ItemStatus = "";
  2619. weekItem.PlanKittingDate = DateTime.Now;
  2620. weekItem.Year = weekTime.Year;
  2621. weekItem.Month = weekTime.Month;
  2622. weekItem.WeekSeq = WeekOfMonth(weekTime, 1);
  2623. weekItem.PlanMonth = kMonth;
  2624. weekItem.tenant_id = input.tenant_id;
  2625. weekItem.factory_id = input.factory_id;
  2626. weekItem.company_id = input.company_id;
  2627. weekItem.org_id = input.org_id;
  2628. weekItem.create_time = DateTime.Now;
  2629. weekItem.DistributionChannel = item.distributionchannel;
  2630. weekItem.IsReplenishmentModel = "N";
  2631. if (item.area == "国内" || item.area == "中国")
  2632. {
  2633. weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value;
  2634. weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value.AddDays(days);
  2635. }
  2636. else
  2637. {
  2638. weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value;
  2639. weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value.AddDays(days);
  2640. }
  2641. weekItem.AssembleHours = 0;
  2642. weekItem.HeatSealHours = 0;
  2643. weekItem.PackageHours = 0;
  2644. weekItem.TotalHours = 0;
  2645. //Q2023/11/15的需求同一周有相同物料的工单不继续生成,不考虑数量的偏差
  2646. if (!weekProductPlanList.Any(a => a.ItemNumber == item.number && a.Week == weekItem.Week))
  2647. {
  2648. weekPlan.Add(weekItem);
  2649. moList.Add(mes_Morder);
  2650. moentryList.Add(mes_Moentry);
  2651. }
  2652. }
  2653. if (k == 11)
  2654. {
  2655. var MonthMoTotal = moList.Find(a => a.product_code == itemSeq && (
  2656. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 56).AddDays(-days) ||
  2657. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 63).AddDays(-days) ||
  2658. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 70).AddDays(-days) ||
  2659. a.moentry_sys_etime == GetNextMonday().AddDays(28 + 77).AddDays(-days)));
  2660. if (MonthMoTotal != null)
  2661. {
  2662. if (MonthMoTotal.need_number > 0)
  2663. {
  2664. var itemMaster = itemMasterList.Find(i => i.ItemNum == itemSeq);
  2665. if (itemMaster != null && itemMaster.MinOrd > 0)
  2666. {
  2667. //考虑生产批量的计算逻辑
  2668. decimal productQty;
  2669. bool exist = minordsalesQty.TryGetValue(itemSeq, out productQty);
  2670. if (exist)
  2671. {
  2672. //不需要生产
  2673. if (MonthMoTotal.need_number <= productQty)
  2674. {
  2675. minordsalesQty[itemSeq] -= MonthMoTotal.need_number.GetValueOrDefault();
  2676. moList.Remove(MonthMoTotal);
  2677. moentryList.RemoveAll(a => a.moentry_mono == MonthMoTotal.morder_no);
  2678. weekPlan.RemoveAll(a => a.ProductionOrder == MonthMoTotal.morder_no);
  2679. }
  2680. else
  2681. {
  2682. //需要生产但是小于生产批量按生产批量生产,大于生产批量不需要改动
  2683. if (MonthMoTotal.need_number - productQty < itemMaster.MinOrd)
  2684. {
  2685. decimal needProductQty = MonthMoTotal.need_number.GetValueOrDefault() - productQty;
  2686. minordsalesQty[itemSeq] = Math.Ceiling(itemMaster.MinOrd) - needProductQty;
  2687. MonthMoTotal.morder_production_number = Math.Ceiling(itemMaster.MinOrd);
  2688. MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd);
  2689. MonthMoTotal.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(70).AddDays(-ProductTime(routingOps, MonthMoTotal.product_code, input.factory_id.ToString(), MonthMoTotal.need_number.GetValueOrDefault()) - days);
  2690. MonthMoTotal.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(70).AddDays(-days);
  2691. moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).morder_production_number = Math.Ceiling(itemMaster.MinOrd);
  2692. moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).need_number = Math.Ceiling(itemMaster.MinOrd);
  2693. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanStartDate = MonthMoTotal.moentry_sys_stime;
  2694. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Week = $"WK{GetWeekOfYear(MonthMoTotal.moentry_sys_stime.Value).ToString("00")}";
  2695. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Qty = MonthMoTotal.morder_production_number.Value;
  2696. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Year = GetNextMonday().AddDays(28).AddDays(70).Year;
  2697. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Month = GetNextMonday().AddDays(28).AddDays(70).Month;
  2698. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(70), 1);
  2699. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(70).Year}-{GetNextMonday().AddDays(28).AddDays(70).Month.ToString("00")}";
  2700. if (item.area == "国内" || item.area == "中国")
  2701. {
  2702. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value;
  2703. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days);
  2704. }
  2705. else
  2706. {
  2707. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value;
  2708. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days);
  2709. }
  2710. }
  2711. }
  2712. }
  2713. else
  2714. {
  2715. if (MonthMoTotal.need_number < Math.Ceiling(itemMaster.MinOrd))
  2716. {
  2717. minordsalesQty[itemSeq] = Math.Ceiling(itemMaster.MinOrd) - MonthMoTotal.need_number.Value;
  2718. MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd);
  2719. MonthMoTotal.morder_production_number = Math.Ceiling(itemMaster.MinOrd);
  2720. MonthMoTotal.need_number = Math.Ceiling(itemMaster.MinOrd);
  2721. MonthMoTotal.moentry_sys_stime = GetNextMonday().AddDays(28).AddDays(70).AddDays(-ProductTime(routingOps, MonthMoTotal.product_code, input.factory_id.ToString(), MonthMoTotal.need_number.GetValueOrDefault()) - days);
  2722. MonthMoTotal.moentry_sys_etime = GetNextMonday().AddDays(28).AddDays(70).AddDays(-days);
  2723. moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).morder_production_number = Math.Ceiling(itemMaster.MinOrd);
  2724. moentryList.Find(a => a.moentry_mono == MonthMoTotal.morder_no).need_number = Math.Ceiling(itemMaster.MinOrd);
  2725. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanStartDate = MonthMoTotal.moentry_sys_stime;
  2726. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Week = $"WK{GetWeekOfYear(MonthMoTotal.moentry_sys_stime.Value).ToString("00")}";
  2727. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Qty = MonthMoTotal.morder_production_number.Value;
  2728. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Year = GetNextMonday().AddDays(28).AddDays(70).Year;
  2729. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).Month = GetNextMonday().AddDays(28).AddDays(70).Month;
  2730. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).WeekSeq = WeekOfMonth(GetNextMonday().AddDays(28).AddDays(70), 1);
  2731. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).PlanMonth = $"{GetNextMonday().AddDays(28).AddDays(70).Year}-{GetNextMonday().AddDays(28).AddDays(70).Month.ToString("00")}";
  2732. if (item.area == "国内" || item.area == "中国")
  2733. {
  2734. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value;
  2735. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days);
  2736. }
  2737. else
  2738. {
  2739. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).SterilizationDate = MonthMoTotal.moentry_sys_etime.Value;
  2740. weekPlan.Find(a => a.ProductionOrder == MonthMoTotal.morder_no).InStockDate = MonthMoTotal.moentry_sys_etime.Value.AddDays(days);
  2741. }
  2742. }
  2743. }
  2744. var planBOM = boms.Find(b => b.item_number == itemSeq);
  2745. var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList();
  2746. var returnlist = ObjectMapper.Map<List<b_bom_pretreatment>, List<BomChildExamineDto>>(pretreament);
  2747. returnlist = returnlist.OrderBy(s => s.num_order).ToList();
  2748. var level1Dto = returnlist[0];
  2749. level1Dto.needCount = MonthMoTotal.need_number.GetValueOrDefault();
  2750. CaclMaterialShortage(returnlist);
  2751. foreach (var r in returnlist)
  2752. {
  2753. if (r.item_number != itemSeq && r.erp_cls == 1 && !string.IsNullOrEmpty(r.bom_number))
  2754. {
  2755. if (subProductItem.ContainsKey(r.item_number))
  2756. {
  2757. subProductItem[r.item_number] += r.needCount;
  2758. }
  2759. else
  2760. {
  2761. subProductItem.Add(r.item_number, r.needCount);
  2762. subProductItemModel.Add(r.item_number, r);
  2763. }
  2764. }
  2765. }
  2766. }
  2767. else
  2768. {
  2769. var planBOM = boms.Find(b => b.item_number == itemSeq);
  2770. var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList();
  2771. var returnlist = ObjectMapper.Map<List<b_bom_pretreatment>, List<BomChildExamineDto>>(pretreament);
  2772. returnlist = returnlist.OrderBy(s => s.num_order).ToList();
  2773. var level1Dto = returnlist[0];
  2774. level1Dto.needCount = MonthMoTotal.need_number.GetValueOrDefault();
  2775. CaclMaterialShortage(returnlist);
  2776. foreach (var r in returnlist)
  2777. {
  2778. if (r.item_number != itemSeq && r.erp_cls == 1 && !string.IsNullOrEmpty(r.bom_number))
  2779. {
  2780. if (subProductItem.ContainsKey(r.item_number))
  2781. {
  2782. subProductItem[r.item_number] += r.needCount;
  2783. }
  2784. else
  2785. {
  2786. subProductItem.Add(r.item_number, r.needCount);
  2787. subProductItemModel.Add(r.item_number, r);
  2788. }
  2789. }
  2790. }
  2791. }
  2792. }
  2793. else
  2794. {
  2795. moList.Remove(MonthMoTotal);
  2796. moentryList.RemoveAll(a => a.moentry_mono == MonthMoTotal.morder_no);
  2797. weekPlan.RemoveAll(a => a.ProductionOrder == MonthMoTotal.morder_no);
  2798. }
  2799. }
  2800. }
  2801. }
  2802. }
  2803. }
  2804. }
  2805. #region
  2806. //滚动12周逻辑保留
  2807. //for (int k = 0; k < 12; k++)
  2808. //{
  2809. // var weekTime = GetNextMonday().AddDays(28);//增加四周
  2810. // weekTime = weekTime.AddDays(7 * k);
  2811. // string kMonth = $"{weekTime.Year}-{weekTime.Month.ToString("00")}";
  2812. // var monthWeekPlan = planList.Where(a => a.planmonth == kMonth).ToList();
  2813. // var ropList = planList.Where(t=>shipPlanList.Select(s => s.SAPItemNumber).ToList().Contains(t.number)).Select(t => t.number).Distinct().ToList();
  2814. // foreach (var itemSeq in ropList)
  2815. // {
  2816. // var monthPlanItem = monthPlan.Find(x => x.ItemNumber == itemSeq);
  2817. // //瑞奇国科海王
  2818. // var monthPlanTotal = monthWeekPlan.Where(x => x.number == itemSeq).ToList();
  2819. // if (monthPlanTotal != null && monthPlanTotal.Count > 0)
  2820. // {
  2821. // var item = monthPlanTotal[0];
  2822. // //瑞奇补货计划!Y5 + 瑞奇补货计划!Z5 + 国科补货计划!Y5 + 国科补货计划!Z5 + 海王补货计划!Y4 + 海王补货计划!Z4
  2823. // var itemQty = monthPlanTotal.Sum(a => a.montheop1) + monthPlanTotal.Sum(a => a.montheop2);
  2824. // //每次都是发布12周,每个月4周,不用判断存不存在(退市的可能没有)
  2825. // int days = 15;
  2826. // if (item.area != "国内" && item.area != "中国")
  2827. // {
  2828. // days = 8;
  2829. // }
  2830. // if (itemQty > 0)
  2831. // {
  2832. // var bom = bomList.Find(b => b.item_number == itemSeq);
  2833. // var ic_item = itemList.Find(b => b.number == itemSeq);
  2834. // mes_morder mes_Morder = new mes_morder();
  2835. // mes_Morder.GenerateNewId(help.NextId());
  2836. // mes_Morder.morder_type = MorderEnum.JhMorder;
  2837. // mes_Morder.work_order_type = MorderEnum.CgMorder;
  2838. // mes_Morder.morder_state = "";
  2839. // mes_Morder.morder_no = Guid.NewGuid().ToString();
  2840. // mes_Morder.fms_number = ic_item.fms_number;
  2841. // mes_Morder.bom_number = bom.bom_number;
  2842. // mes_Morder.fmodel = ic_item.model;
  2843. // mes_Morder.moentry_startup_status = 0;
  2844. // mes_Morder.tenant_id = input.tenant_id;
  2845. // mes_Morder.factory_id = input.factory_id;
  2846. // mes_Morder.company_id = input.company_id;
  2847. // mes_Morder.org_id = input.org_id;
  2848. // mes_Morder.product_code = ic_item.number;
  2849. // mes_Morder.product_name = ic_item.name;
  2850. // mes_Morder.morder_date = DateTime.Now.Date.AddDays(1);
  2851. // mes_Morder.moentry_prd = null;
  2852. // mes_Morder.moentry_prdname = null;
  2853. // mes_Morder.moentry_wrkc = null;
  2854. // mes_Morder.moentry_wrkcname = null;
  2855. // mes_Morder.picking_qty = 0;
  2856. // mes_Morder.unit = ic_item.unit;
  2857. // mes_Morder.morder_production_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  2858. // mes_Morder.need_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4);
  2859. // //成品半成品取周一为入库时间开始往前推
  2860. // mes_Morder.moentry_sys_stime = weekTime.AddDays(-ProductTime(routingOps, ic_item.number, input.factory_id.ToString(), mes_Morder.need_number.GetValueOrDefault()) - days);
  2861. // mes_Morder.moentry_sys_etime = weekTime.AddDays(-days);
  2862. // mes_Morder.remaining_number = 0;
  2863. // mes_Morder.create_time = DateTime.Now;
  2864. // mes_Morder.bang_id = bang_id;
  2865. // //生成工单子表数据
  2866. // mes_moentry mes_Moentry = new mes_moentry();
  2867. // mes_Moentry.GenerateNewId(help.NextId());
  2868. // mes_Moentry.moentry_moid = mes_Morder.Id;
  2869. // mes_Moentry.moentry_mono = mes_Morder.morder_no;
  2870. // mes_Moentry.unit = ic_item.unit;
  2871. // mes_Moentry.morder_production_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); ;
  2872. // mes_Moentry.need_number = Math.Ceiling(itemQty.GetValueOrDefault() / 4); ;
  2873. // mes_Moentry.remaining_number = 0;
  2874. // mes_Moentry.tenant_id = input.tenant_id;
  2875. // mes_Moentry.factory_id = input.factory_id;
  2876. // mes_Moentry.company_id = input.company_id;
  2877. // mes_Moentry.org_id = input.org_id;
  2878. // mes_Moentry.create_time = DateTime.Now;
  2879. // mes_Moentry.bang_id = bang_id;
  2880. // ReplenishmentWeekPlan weekItem = new ReplenishmentWeekPlan();
  2881. // weekItem.Priority = 1;
  2882. // weekItem.Area = item.area;
  2883. // weekItem.PlanStartDate = mes_Morder.moentry_sys_stime.GetValueOrDefault();
  2884. // weekItem.Week = $"WK{GetWeekOfYear(mes_Morder.moentry_sys_stime.Value).ToString("00")}";
  2885. // weekItem.OrderNO = Guid.NewGuid().ToString();
  2886. // weekItem.ProductionOrder = mes_Morder.morder_no;
  2887. // weekItem.SAPOrderNO = "";
  2888. // weekItem.OrderType = "量产";
  2889. // weekItem.ProductionBatch = "";
  2890. // weekItem.ProductionStatus = "";
  2891. // weekItem.ProdLine = item.ProdLine;
  2892. // weekItem.ProdRange = item.ProdRange;
  2893. // weekItem.Line = monthPlanItem?.WorkshopLine;
  2894. // weekItem.ItemNumber = item.number;
  2895. // weekItem.Model = item.model;
  2896. // weekItem.Languages = item.Languages;
  2897. // weekItem.Qty = mes_Morder.morder_production_number.Value;
  2898. // weekItem.ItemStatus = "";
  2899. // weekItem.PlanKittingDate = DateTime.Now;
  2900. // weekItem.Year = weekTime.Year;
  2901. // weekItem.Month = weekTime.Month;
  2902. // weekItem.WeekSeq = WeekOfMonth(weekTime, 1);
  2903. // weekItem.PlanMonth = kMonth;
  2904. // weekItem.tenant_id = input.tenant_id;
  2905. // weekItem.factory_id = input.factory_id;
  2906. // weekItem.company_id = input.company_id;
  2907. // weekItem.org_id = input.org_id;
  2908. // weekItem.create_time = DateTime.Now;
  2909. // weekItem.DistributionChannel = item.distributionchannel;
  2910. // weekItem.IsReplenishmentModel = "N";
  2911. // if (item.area == "国内" || item.area == "中国")
  2912. // {
  2913. // weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value;
  2914. // weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value.AddDays(days);
  2915. // }
  2916. // else
  2917. // {
  2918. // weekItem.SterilizationDate = mes_Morder.moentry_sys_etime.Value;
  2919. // weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value.AddDays(days);
  2920. // }
  2921. // weekItem.AssembleHours = 0;
  2922. // weekItem.HeatSealHours = 0;
  2923. // weekItem.PackageHours = 0;
  2924. // weekItem.TotalHours = 0;
  2925. // //Q2023/11/15的需求同一周有相同物料的工单不继续生成,不考虑数量的偏差
  2926. // if (!weekProductPlanList.Any(a => a.ItemNumber == item.number && a.Week == weekItem.Week))
  2927. // {
  2928. // weekPlan.Add(weekItem);
  2929. // moList.Add(mes_Morder);
  2930. // moentryList.Add(mes_Moentry);
  2931. // var planBOM = boms.Find(b => b.item_number == itemSeq);
  2932. // var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList();
  2933. // var returnlist = ObjectMapper.Map<List<b_bom_pretreatment>, List<BomChildExamineDto>>(pretreament);
  2934. // returnlist = returnlist.OrderBy(s => s.num_order).ToList();
  2935. // var level1Dto = returnlist[0];
  2936. // level1Dto.needCount = itemQty.GetValueOrDefault();
  2937. // CaclMaterialShortage(returnlist);
  2938. // foreach (var r in returnlist)
  2939. // {
  2940. // if (r.item_number != itemSeq && r.erp_cls == 1 && !string.IsNullOrEmpty(r.bom_number))
  2941. // {
  2942. // if (subProductItem.ContainsKey(r.item_number))
  2943. // {
  2944. // subProductItem[r.item_number] += r.needCount;
  2945. // }
  2946. // else
  2947. // {
  2948. // subProductItem.Add(r.item_number, r.needCount);
  2949. // subProductItemModel.Add(r.item_number, r);
  2950. // }
  2951. // }
  2952. // }
  2953. // }
  2954. // }
  2955. // }
  2956. // }
  2957. //}
  2958. #endregion
  2959. List<string> subItems = new List<string>();
  2960. for (int j = 0; j < 3; j++)
  2961. {
  2962. var jweekTime = GetNextMonday().AddDays(28);
  2963. jweekTime = jweekTime.AddDays(28 * j);
  2964. string jMonth = $"{jweekTime.Year}-{jweekTime.Month.ToString("00")}";
  2965. subItems.Add(jMonth);
  2966. }
  2967. var weeksubPlanList = _replenishmentWeekPlan.GetListAsync(a => subItems.Contains(a.PlanMonth) && !a.IsDeleted && a.factory_id == input.factory_id && a.IsReplenishmentModel == "N").Result;
  2968. //中间件钉匣泡壳四周开一张工单
  2969. for (int i = 0; i < 3; i++)
  2970. {
  2971. var weekTime = GetNextMonday().AddDays(28);
  2972. weekTime = weekTime.AddDays(28 * i);
  2973. var weekofMonth = WeekOfMonth(weekTime, 1);
  2974. string kMonth = $"{weekTime.Year}-{weekTime.Month.ToString("00")}";
  2975. if (prodLines.Count == 0)
  2976. {
  2977. prodLines = _prodLineDetail.Select(p => subProductItem.Keys.Contains(p.Part) && p.Domain == input.factory_id.ToString() && p.IsActive && routingOpList.Select(m => m.Op).Contains(p.Op)).OrderBy(x => x.Sequence).ToList();
  2978. }
  2979. if (lineMasters.Count == 0)
  2980. {
  2981. lineMasters = _lineMaster.Select(p => prodLines.Select(a => a.Line).Contains(p.Line) && p.Domain == input.factory_id.ToString() && p.IsActive).ToList();
  2982. }
  2983. var middleItemList = _itemMaster.Select(a => subProductItem.Keys.Contains(a.ItemNum) && a.Domain == input.factory_id.ToString());
  2984. foreach (var key in subProductItem.Keys)
  2985. {
  2986. var itemQty = subProductItem[key] / 3;
  2987. var middle = middleItemList.Find(m => m.ItemNum == key);
  2988. var middleItem = middle.MinOrd;
  2989. if (middleItem > 0)
  2990. {
  2991. if (itemQty < middleItem)
  2992. itemQty = middleItem;
  2993. if (middle.ItemType == "RS30" && middle.PurMfg == "L" && middle.OrdMult > 0)
  2994. {
  2995. itemQty = Math.Ceiling(Math.Ceiling(itemQty.GetValueOrDefault() / middle.OrdMult) * middle.OrdMult);
  2996. }
  2997. else
  2998. {
  2999. itemQty = Math.Ceiling(itemQty.GetValueOrDefault());
  3000. }
  3001. }
  3002. else
  3003. {
  3004. itemQty = Math.Ceiling(itemQty.GetValueOrDefault());
  3005. }
  3006. if (!weeksubPlanList.Any(a => a.ItemNumber == subProductItemModel[key].item_number && a.PlanMonth == kMonth) && itemQty > 0)
  3007. {
  3008. mes_morder mes_Morder = new mes_morder();
  3009. mes_Morder.GenerateNewId(help.NextId());
  3010. mes_Morder.morder_type = MorderEnum.JhMorder;
  3011. mes_Morder.work_order_type = MorderEnum.CgMorder;
  3012. mes_Morder.morder_state = "";
  3013. mes_Morder.morder_no = Guid.NewGuid().ToString();
  3014. mes_Morder.fms_number = "";
  3015. mes_Morder.bom_number = subProductItemModel[key].bom_number;
  3016. mes_Morder.fmodel = subProductItemModel[key].model;
  3017. mes_Morder.moentry_startup_status = 0;
  3018. mes_Morder.tenant_id = input.tenant_id;
  3019. mes_Morder.factory_id = input.factory_id;
  3020. mes_Morder.company_id = input.company_id;
  3021. mes_Morder.org_id = input.org_id;
  3022. mes_Morder.product_code = subProductItemModel[key].item_number;
  3023. mes_Morder.product_name = subProductItemModel[key].item_name;
  3024. mes_Morder.morder_date = DateTime.Now.Date.AddDays(1);
  3025. mes_Morder.moentry_prd = null;
  3026. mes_Morder.moentry_prdname = null;
  3027. mes_Morder.moentry_wrkc = null;
  3028. mes_Morder.moentry_wrkcname = null;
  3029. mes_Morder.picking_qty = 0;
  3030. mes_Morder.unit = subProductItemModel[key].unit;
  3031. mes_Morder.morder_production_number = itemQty;
  3032. mes_Morder.need_number = itemQty;
  3033. //成品半成品取周一为入库时间开始往前推
  3034. mes_Morder.moentry_sys_stime = weekTime.AddDays(-ProductTime(routingOps, subProductItemModel[key].item_number, input.factory_id.ToString(), mes_Morder.need_number.GetValueOrDefault()));
  3035. mes_Morder.moentry_sys_etime = weekTime;
  3036. mes_Morder.remaining_number = 0;
  3037. mes_Morder.create_time = DateTime.Now;
  3038. mes_Morder.bang_id = bang_id;
  3039. //生成工单子表数据
  3040. mes_moentry mes_Moentry = new mes_moentry();
  3041. mes_Moentry.GenerateNewId(help.NextId());
  3042. mes_Moentry.moentry_moid = mes_Morder.Id;
  3043. mes_Moentry.moentry_mono = mes_Morder.morder_no;
  3044. mes_Moentry.unit = subProductItemModel[key].unit;
  3045. mes_Moentry.morder_production_number = itemQty;
  3046. mes_Moentry.need_number = itemQty;
  3047. mes_Moentry.remaining_number = 0;
  3048. mes_Moentry.tenant_id = input.tenant_id;
  3049. mes_Moentry.factory_id = input.factory_id;
  3050. mes_Moentry.company_id = input.company_id;
  3051. mes_Moentry.org_id = input.org_id;
  3052. mes_Moentry.create_time = DateTime.Now;
  3053. mes_Moentry.bang_id = bang_id;
  3054. var prodLine = prodLines.Where(x => x.Part == key).OrderBy(x => x.Sequence).FirstOrDefault();
  3055. ReplenishmentWeekPlan weekItem = new ReplenishmentWeekPlan();
  3056. weekItem.Priority = 1;
  3057. weekItem.Area = "";
  3058. weekItem.PlanStartDate = mes_Morder.moentry_sys_stime.GetValueOrDefault();
  3059. weekItem.Week = $"WK{GetWeekOfYear(mes_Morder.moentry_sys_stime.Value).ToString("00")}";
  3060. weekItem.OrderNO = Guid.NewGuid().ToString();
  3061. weekItem.ProductionOrder = mes_Morder.morder_no;
  3062. weekItem.SAPOrderNO = "";
  3063. weekItem.OrderType = "量产";
  3064. weekItem.ProductionBatch = "";
  3065. weekItem.ProductionStatus = "";
  3066. weekItem.ProdLine = "";
  3067. weekItem.ProdRange = "";
  3068. if (prodLine != null && lineMasters.Find(b => b.Line == prodLine.Line) != null)
  3069. {
  3070. weekItem.Line = lineMasters.Find(b => b.Line == prodLine.Line).Describe;
  3071. }
  3072. else
  3073. {
  3074. weekItem.Line = "";
  3075. }
  3076. weekItem.ItemNumber = key;
  3077. weekItem.Model = subProductItemModel[key].model;
  3078. weekItem.Languages = "";
  3079. weekItem.Qty = mes_Morder.morder_production_number.Value;
  3080. weekItem.ItemStatus = "";
  3081. weekItem.PlanKittingDate = DateTime.Now;
  3082. weekItem.Year = mes_Morder.moentry_sys_stime.Value.Year;
  3083. weekItem.Month = mes_Morder.moentry_sys_stime.Value.Month;
  3084. weekItem.PlanMonth = kMonth;
  3085. weekItem.WeekSeq = weekofMonth;
  3086. weekItem.tenant_id = input.tenant_id;
  3087. weekItem.factory_id = input.factory_id;
  3088. weekItem.company_id = input.company_id;
  3089. weekItem.org_id = input.org_id;
  3090. weekItem.create_time = DateTime.Now;
  3091. weekItem.DistributionChannel = "瑞奇";
  3092. weekItem.IsReplenishmentModel = "N";
  3093. weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value;
  3094. weekItem.AssembleHours = 0;
  3095. weekItem.HeatSealHours = 0;
  3096. weekItem.PackageHours = 0;
  3097. weekItem.TotalHours = 0;
  3098. weekPlan.Add(weekItem);
  3099. moList.Add(mes_Morder);
  3100. moentryList.Add(mes_Moentry);
  3101. }
  3102. }
  3103. }
  3104. var morder_noList = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "M5", moList.Count, "", 1);
  3105. var OrderNOList = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "MPO", moList.Count, "", 1);
  3106. for (int i = 0; i < moList.Count; i++)
  3107. {
  3108. moList[i].morder_no = morder_noList[i].NbrResult;
  3109. moentryList[i].moentry_mono = morder_noList[i].NbrResult;
  3110. weekPlan[i].ProductionOrder = morder_noList[i].NbrResult;
  3111. weekPlan[i].OrderNO = OrderNOList[i].NbrResult;
  3112. }
  3113. await _businessDbContext.AddRangeAsync(moList);
  3114. await _businessDbContext.AddRangeAsync(moentryList);
  3115. //await _businessDbContext.SaveChangesAsync();
  3116. //批量保存 后期考虑子工单
  3117. List<WorkOrdMaster> workOrdSave = new List<WorkOrdMaster>();
  3118. List<WorkOrdRouting> workOrdRoutingSave = new List<WorkOrdRouting>();
  3119. List<WorkOrdDetail> workOrdDetails = new List<WorkOrdDetail>();
  3120. if (moList.Any())
  3121. {
  3122. //同步工单
  3123. CreateWorkOrdDates(moList, moentryList, routingOps, workOrdSave, workOrdRoutingSave, workOrdDetails, new List<b_examine_result>(), new List<b_bom_child_examine>());
  3124. }
  3125. if (workOrdSave.Any())
  3126. {
  3127. await _businessDbContext.AddRangeAsync(workOrdSave);
  3128. //CalcPriority(input.factory_id.ToString());
  3129. RefreshPriority(null, input.factory_id.ToString());
  3130. }
  3131. var DBworkOrdList = _workOrdMaster.Select(a => workOrdSave.Count > 0 && a.Domain == workOrdSave[0].Domain && workOrdSave.Select(c => c.WorkOrd).Contains(a.WorkOrd));
  3132. if (workOrdRoutingSave.Any())
  3133. {
  3134. workOrdRoutingSave.ForEach(c =>
  3135. {
  3136. c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
  3137. });
  3138. await _businessDbContext.AddRangeAsync(workOrdRoutingSave);
  3139. }
  3140. if (workOrdDetails.Any())
  3141. {
  3142. workOrdDetails.ForEach(c =>
  3143. {
  3144. c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
  3145. });
  3146. await _businessDbContext.AddRangeAsync(workOrdDetails);
  3147. }
  3148. await _businessBangDbContext.SaveChangesAsync();
  3149. await PlanOrderResourceCheck(moList.OrderBy(a => a.moentry_sys_stime).ToList(), moentryList, bang_id, "", false, false);
  3150. var examine_resultList = _mysql_examine_result.GetListAsync(a => a.bangid == bang_id).Result;
  3151. weekPlan.ForEach(a =>
  3152. {
  3153. if (a.IsReplenishmentModel == "N")
  3154. {
  3155. var moItem = examine_resultList.Find(b => b.morder_no == a.ProductionOrder);
  3156. List<RoutingOpDetail> routingOp = routingOps.Where(x => x.RoutingCode == a.ItemNumber).ToList();
  3157. //组装标准工时
  3158. var Assembly = routingOp.Where(x => x.Ufld1 == "组装" && x.MilestoneOp).FirstOrDefault();
  3159. //热封标准工时
  3160. var HeatSealing = routingOp.Where(x => x.Ufld1 == "热封" && x.MilestoneOp).FirstOrDefault();
  3161. //包装标准工时
  3162. var Packaging = routingOp.Where(x => x.Descr == "包装" && x.MilestoneOp).FirstOrDefault();
  3163. if (moItem != null && moItem.kitting_times < a.PlanStartDate)
  3164. {
  3165. a.ItemStatus = "齐套";
  3166. a.PlanKittingDate = moItem.kitting_times;
  3167. a.AssembleHours = Assembly == null ? 0 : Assembly.RunTime * a.Qty;
  3168. a.HeatSealHours = HeatSealing == null ? 0 : HeatSealing.RunTime * a.Qty;
  3169. a.PackageHours = Packaging == null ? 0 : Packaging.RunTime * a.Qty;
  3170. a.TotalHours = a.AssembleHours + a.HeatSealHours + a.PackageHours;
  3171. }
  3172. else
  3173. {
  3174. a.ItemStatus = "欠料";
  3175. a.PlanKittingDate = moItem.kitting_times;
  3176. a.AssembleHours = Assembly == null ? 0 : Assembly.RunTime * a.Qty;
  3177. a.HeatSealHours = HeatSealing == null ? 0 : HeatSealing.RunTime * a.Qty;
  3178. a.PackageHours = Packaging == null ? 0 : Packaging.RunTime * a.Qty;
  3179. a.TotalHours = a.AssembleHours + a.HeatSealHours + a.PackageHours;
  3180. }
  3181. }
  3182. });
  3183. await _businessDbContext.AddRangeAsync(weekPlan);
  3184. await _businessBangDbContext.SaveChangesAsync();
  3185. return "OK";
  3186. }
  3187. /// <summary>
  3188. /// 根据周计划生成周工单
  3189. /// </summary>
  3190. /// <param name="input"></param>
  3191. /// <returns></returns>
  3192. public async Task<string> CalcTempWeekPlan(InputDto input)
  3193. {
  3194. //var IsActived = _AccountValidityAppService.IsActived();
  3195. //if (!IsActived)
  3196. //{
  3197. // return "此账号已限制访问";
  3198. //}
  3199. await ClearDO(input.factory_id.ToString());
  3200. routingOps = _routingOpDetail.Select(p => p.Domain == input.factory_id.ToString()).ToList();
  3201. long bang_id = help.NextId();
  3202. var weekplans = _replenishmentWeekPlan.GetListAsync(a => a.IsReplenishmentModel == "N" && string.IsNullOrEmpty(a.ProductionStatus) && string.IsNullOrEmpty(a.ProductionOrder) && a.factory_id == input.factory_id).Result;
  3203. if (weekplans.Any())
  3204. {
  3205. input.company_id = weekplans[0].company_id.GetValueOrDefault();
  3206. input.tenant_id = weekplans[0].tenant_id.GetValueOrDefault();
  3207. input.org_id = weekplans[0].org_id.GetValueOrDefault();
  3208. }
  3209. var itemIds = weekplans.Select(a => a.ItemNumber).Distinct().ToList();
  3210. var items = _itemMaster.Select(a => itemIds.Contains(a.ItemNum));
  3211. List<mes_morder> moList = new List<mes_morder>();
  3212. List<mes_moentry> moentryList = new List<mes_moentry>();
  3213. //获取BOM用于分解到原材料
  3214. var boms = _ic_bom.GetListAsync(a => weekplans.Select(p => p.ItemNumber).ToList().Contains(a.item_number) && a.factory_id == input.factory_id).Result;
  3215. var pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
  3216. List<mo_ic_bom> autoCreates = new List<mo_ic_bom>();
  3217. boms.ForEach(p =>
  3218. {
  3219. if (!pretreatments.Where(s => s.sourceid == p.mysql_id).Any())
  3220. {
  3221. autoCreates.Add(p);
  3222. }
  3223. });
  3224. if (autoCreates.Any())
  3225. {
  3226. AutoCreateBomBill(input.company_id.ToString(), autoCreates);
  3227. pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
  3228. }
  3229. Dictionary<string, decimal?> subProductItem = new Dictionary<string, decimal?>();
  3230. Dictionary<string, BomChildExamineDto> subProductItemModel = new Dictionary<string, BomChildExamineDto>();
  3231. Dictionary<string, string> subProductIds = new Dictionary<string, string>();
  3232. List<ReplenishmentWeekPlan> WeekPlan = new List<ReplenishmentWeekPlan>();
  3233. List<ReplenishmentWeekPlan> SubWeekPlan = new List<ReplenishmentWeekPlan>();
  3234. foreach (var item in weekplans)
  3235. {
  3236. var planBOM = boms.Find(b => b.item_number == item.ItemNumber);
  3237. if (planBOM == null)
  3238. {
  3239. continue;
  3240. }
  3241. WeekPlan.Add(item);
  3242. var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList();
  3243. var returnlist = ObjectMapper.Map<List<b_bom_pretreatment>, List<BomChildExamineDto>>(pretreament);
  3244. var level1Dto = returnlist[0];
  3245. level1Dto.needCount = item.Qty;
  3246. returnlist = returnlist.OrderBy(s => s.num_order).ToList();
  3247. CaclMaterialShortage(returnlist);
  3248. foreach (var r in returnlist)
  3249. {
  3250. if (r.item_number != item.ItemNumber && r.erp_cls == 1 && !string.IsNullOrEmpty(r.bom_number))
  3251. {
  3252. if (subProductItem.ContainsKey(r.item_number))
  3253. {
  3254. subProductItem[r.item_number] += r.needCount;
  3255. subProductIds[r.item_number] += "," + item.Id.ToString();
  3256. }
  3257. else
  3258. {
  3259. subProductItem.Add(r.item_number, r.needCount);
  3260. subProductIds.Add(r.item_number, item.Id.ToString());
  3261. subProductItemModel.Add(r.item_number, r);
  3262. }
  3263. }
  3264. }
  3265. mes_morder mes_Morder = new mes_morder();
  3266. mes_Morder.GenerateNewId(help.NextId());
  3267. mes_Morder.morder_type = MorderEnum.JhMorder;
  3268. mes_Morder.work_order_type = MorderEnum.CgMorder;
  3269. mes_Morder.morder_state = "";
  3270. mes_Morder.morder_no = Guid.NewGuid().ToString();
  3271. mes_Morder.fms_number = "";
  3272. mes_Morder.bom_number = item.ItemNumber;
  3273. mes_Morder.fmodel = item.Model;
  3274. mes_Morder.moentry_startup_status = 0;
  3275. mes_Morder.tenant_id = input.tenant_id;
  3276. mes_Morder.factory_id = input.factory_id;
  3277. mes_Morder.company_id = input.company_id;
  3278. mes_Morder.org_id = input.org_id;
  3279. mes_Morder.product_code = item.ItemNumber;
  3280. mes_Morder.product_name = items.Find(a => a.ItemNum == item.ItemNumber).Descr;
  3281. mes_Morder.morder_date = DateTime.Now.Date.AddDays(1);
  3282. mes_Morder.moentry_prd = null;
  3283. mes_Morder.moentry_prdname = null;
  3284. mes_Morder.moentry_wrkc = null;
  3285. mes_Morder.moentry_wrkcname = null;
  3286. mes_Morder.picking_qty = 0;
  3287. mes_Morder.unit = items.Find(a => a.ItemNum == item.ItemNumber).UM;
  3288. mes_Morder.morder_production_number = item.Qty;
  3289. mes_Morder.need_number = item.Qty;
  3290. //成品半成品取周一为入库时间开始往前推
  3291. mes_Morder.moentry_sys_stime = item.PlanStartDate;
  3292. mes_Morder.moentry_sys_etime = item.InStockDate;
  3293. mes_Morder.remaining_number = 0;
  3294. mes_Morder.create_time = DateTime.Now;
  3295. mes_Morder.bang_id = bang_id;
  3296. //生成工单子表数据
  3297. mes_moentry mes_Moentry = new mes_moentry();
  3298. mes_Moentry.GenerateNewId(help.NextId());
  3299. mes_Moentry.moentry_moid = mes_Morder.Id;
  3300. mes_Moentry.moentry_mono = mes_Morder.morder_no;
  3301. mes_Moentry.unit = items.Find(a => a.ItemNum == item.ItemNumber).UM;
  3302. mes_Moentry.morder_production_number = item.Qty;
  3303. mes_Moentry.need_number = item.Qty;
  3304. mes_Moentry.remaining_number = 0;
  3305. mes_Moentry.tenant_id = input.tenant_id;
  3306. mes_Moentry.factory_id = input.factory_id;
  3307. mes_Moentry.company_id = input.company_id;
  3308. mes_Moentry.org_id = input.org_id;
  3309. mes_Moentry.create_time = DateTime.Now;
  3310. mes_Moentry.bang_id = bang_id;
  3311. moList.Add(mes_Morder);
  3312. moentryList.Add(mes_Moentry);
  3313. }
  3314. weekplans = WeekPlan;
  3315. string kMonth = $"{DateTime.Now.Year}-{DateTime.Now.Month.ToString("00")}";
  3316. var middleItemList = _itemMaster.Select(a => subProductItem.Keys.Contains(a.ItemNum) && a.Domain == input.factory_id.ToString());
  3317. var lineMasters = _lineMaster.Select(p => prodLines.Select(a => a.Line).Contains(p.Line) && p.Domain == input.factory_id.ToString() && p.IsActive).ToList();
  3318. var weekofMonth = WeekOfMonth(DateTime.Now, 1);
  3319. await AsyncItemStockFromWMS(pretreatments.Select(p => p.item_number).ToList(), "");
  3320. var icitemStokc = _mysql_ic_item_stock.GetListAsync(p => pretreatments.Select(pr => pr.item_id).Contains(p.icitem_id) && p.company_id == input.company_id).Result;
  3321. var InProdcutQty = GetProdcutQty(pretreatments.Select(m => m.item_number).ToList(), input);
  3322. foreach (var key in subProductItem.Keys)
  3323. {
  3324. var itemQty = subProductItem[key];
  3325. var ParentNeedCount = subProductItem[key];
  3326. var middle = middleItemList.Find(m => m.ItemNum == key);
  3327. var curStokc = icitemStokc.Find(s => s.icitem_number == key);
  3328. var curInProdcut = InProdcutQty.Find(s => s.ItemNumber == key);
  3329. var curStokcQty = 0m;
  3330. var curInProdcutQty = 0m;
  3331. if (curStokc != null)
  3332. {
  3333. curStokcQty = curStokc.sqty.GetValueOrDefault();
  3334. }
  3335. if (curInProdcut != null)
  3336. {
  3337. curInProdcutQty = curInProdcut.Qty;
  3338. }
  3339. var middleItem = middle.MinOrd;
  3340. if (middleItem > 0)
  3341. {
  3342. if (itemQty < middleItem)
  3343. itemQty = middleItem;
  3344. if (middle.ItemType == "RS30" && middle.PurMfg == "L" && middle.OrdMult > 0)
  3345. {
  3346. itemQty = Math.Ceiling(Math.Ceiling(itemQty.GetValueOrDefault() / middle.OrdMult) * middle.OrdMult);
  3347. }
  3348. else
  3349. {
  3350. itemQty = Math.Ceiling(itemQty.GetValueOrDefault());
  3351. }
  3352. }
  3353. else
  3354. {
  3355. itemQty = Math.Ceiling(itemQty.GetValueOrDefault());
  3356. }
  3357. if (curStokcQty + curInProdcutQty - itemQty >= middle.SafetyStk)
  3358. {
  3359. itemQty = 0;
  3360. }
  3361. else
  3362. {
  3363. //库存加在制满足需求
  3364. if (curStokcQty + curInProdcutQty > itemQty)
  3365. {
  3366. itemQty = Math.Ceiling(curStokcQty + curInProdcutQty - itemQty.GetValueOrDefault());
  3367. //满足需求后剩余数量不满足安全库存需求
  3368. if (itemQty < middle.SafetyStk)
  3369. {
  3370. itemQty = middle.SafetyStk;
  3371. }
  3372. }
  3373. else
  3374. {
  3375. itemQty = Math.Ceiling(itemQty.GetValueOrDefault() - (curStokcQty + curInProdcutQty) + middle.SafetyStk);
  3376. }
  3377. }
  3378. if (itemQty > 0)
  3379. {
  3380. mes_morder mes_Morder = new mes_morder();
  3381. mes_Morder.GenerateNewId(help.NextId());
  3382. mes_Morder.morder_type = MorderEnum.JhMorder;
  3383. mes_Morder.work_order_type = MorderEnum.CgMorder;
  3384. mes_Morder.morder_state = "";
  3385. mes_Morder.morder_no = Guid.NewGuid().ToString();
  3386. mes_Morder.fms_number = "";
  3387. mes_Morder.bom_number = subProductItemModel[key].bom_number;
  3388. mes_Morder.fmodel = subProductItemModel[key].model;
  3389. mes_Morder.moentry_startup_status = 0;
  3390. mes_Morder.tenant_id = input.tenant_id;
  3391. mes_Morder.factory_id = input.factory_id;
  3392. mes_Morder.company_id = input.company_id;
  3393. mes_Morder.org_id = input.org_id;
  3394. mes_Morder.product_code = subProductItemModel[key].item_number;
  3395. mes_Morder.product_name = subProductItemModel[key].item_name;
  3396. mes_Morder.morder_date = DateTime.Now.Date.AddDays(1);
  3397. mes_Morder.moentry_prd = null;
  3398. mes_Morder.moentry_prdname = null;
  3399. mes_Morder.moentry_wrkc = null;
  3400. mes_Morder.moentry_wrkcname = null;
  3401. mes_Morder.picking_qty = 0;
  3402. mes_Morder.unit = subProductItemModel[key].unit;
  3403. mes_Morder.morder_production_number = Math.Ceiling(itemQty.GetValueOrDefault());
  3404. mes_Morder.need_number = Math.Ceiling(itemQty.GetValueOrDefault());
  3405. //成品半成品取周一为入库时间开始往前推
  3406. mes_Morder.moentry_sys_stime = DateTime.Now;
  3407. mes_Morder.moentry_sys_etime = DateTime.Now.AddDays(ProductTime(routingOps, subProductItemModel[key].item_number, input.factory_id.ToString(), mes_Morder.need_number.GetValueOrDefault()));
  3408. mes_Morder.remaining_number = 0;
  3409. mes_Morder.create_time = DateTime.Now;
  3410. mes_Morder.bang_id = bang_id;
  3411. //生成工单子表数据
  3412. mes_moentry mes_Moentry = new mes_moentry();
  3413. mes_Moentry.GenerateNewId(help.NextId());
  3414. mes_Moentry.moentry_moid = mes_Morder.Id;
  3415. mes_Moentry.moentry_mono = mes_Morder.morder_no;
  3416. mes_Moentry.unit = subProductItemModel[key].unit;
  3417. mes_Moentry.morder_production_number = itemQty;
  3418. mes_Moentry.need_number = itemQty;
  3419. mes_Moentry.remaining_number = 0;
  3420. mes_Moentry.tenant_id = input.tenant_id;
  3421. mes_Moentry.factory_id = input.factory_id;
  3422. mes_Moentry.company_id = input.company_id;
  3423. mes_Moentry.org_id = input.org_id;
  3424. mes_Moentry.create_time = DateTime.Now;
  3425. mes_Moentry.bang_id = bang_id;
  3426. var prodLine = prodLines.Where(x => x.Part == key).OrderBy(x => x.Sequence).FirstOrDefault();
  3427. ReplenishmentWeekPlan weekItem = new ReplenishmentWeekPlan();
  3428. weekItem.Priority = 1;
  3429. weekItem.Area = "";
  3430. weekItem.PlanStartDate = mes_Morder.moentry_sys_stime.GetValueOrDefault();
  3431. weekItem.Week = $"WK{GetWeekOfYear(mes_Morder.moentry_sys_stime.Value).ToString("00")}";
  3432. weekItem.OrderNO = Guid.NewGuid().ToString();
  3433. weekItem.ProductionOrder = mes_Morder.morder_no;
  3434. weekItem.SAPOrderNO = "";
  3435. weekItem.OrderType = "量产";
  3436. weekItem.ProductionBatch = "";
  3437. weekItem.ProductionStatus = "";
  3438. weekItem.ProdLine = "";
  3439. weekItem.ProdRange = "";
  3440. if (prodLine != null && lineMasters.Find(b => b.Line == prodLine.Line) != null)
  3441. {
  3442. weekItem.Line = lineMasters.Find(b => b.Line == prodLine.Line).Describe;
  3443. }
  3444. else
  3445. {
  3446. weekItem.Line = "";
  3447. }
  3448. weekItem.ItemNumber = key;
  3449. weekItem.Model = subProductItemModel[key].model;
  3450. weekItem.Languages = "";
  3451. weekItem.Qty = Math.Ceiling(mes_Morder.morder_production_number.Value);
  3452. weekItem.ItemStatus = "";
  3453. weekItem.PlanKittingDate = DateTime.Now;
  3454. weekItem.Year = mes_Morder.moentry_sys_stime.Value.Year;
  3455. weekItem.Month = mes_Morder.moentry_sys_stime.Value.Month;
  3456. weekItem.PlanMonth = kMonth;
  3457. weekItem.WeekSeq = weekofMonth;
  3458. weekItem.tenant_id = input.tenant_id;
  3459. weekItem.factory_id = input.factory_id;
  3460. weekItem.company_id = input.company_id;
  3461. weekItem.org_id = input.org_id;
  3462. weekItem.create_time = DateTime.Now;
  3463. weekItem.DistributionChannel = "瑞奇";
  3464. weekItem.IsReplenishmentModel = "N";
  3465. weekItem.InStockDate = mes_Morder.moentry_sys_etime.Value;
  3466. weekItem.AssembleHours = 0;
  3467. weekItem.HeatSealHours = 0;
  3468. weekItem.PackageHours = 0;
  3469. weekItem.TotalHours = 0;
  3470. weekItem.StokcQty = curStokcQty;
  3471. weekItem.ProdcutQty = curInProdcutQty;
  3472. weekItem.ParentIds = subProductIds[key];
  3473. weekItem.ParentNeedCount = ParentNeedCount.GetValueOrDefault();
  3474. SubWeekPlan.Add(weekItem);
  3475. weekplans.Add(weekItem);
  3476. moList.Add(mes_Morder);
  3477. moentryList.Add(mes_Moentry);
  3478. }
  3479. }
  3480. var morder_noList = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "M5", moList.Count, "", 1);
  3481. for (int i = 0; i < moList.Count; i++)
  3482. {
  3483. moList[i].morder_no = morder_noList[i].NbrResult;
  3484. moentryList[i].moentry_mono = morder_noList[i].NbrResult;
  3485. weekplans[i].ProductionOrder = morder_noList[i].NbrResult;
  3486. }
  3487. await _businessDbContext.AddRangeAsync(SubWeekPlan);
  3488. await _businessDbContext.AddRangeAsync(moList);
  3489. await _businessDbContext.AddRangeAsync(moentryList);
  3490. _businessDbContext.UpdateRange(weekplans);
  3491. //批量保存 后期考虑子工单
  3492. List<WorkOrdMaster> workOrdSave = new List<WorkOrdMaster>();
  3493. List<WorkOrdRouting> workOrdRoutingSave = new List<WorkOrdRouting>();
  3494. List<WorkOrdDetail> workOrdDetails = new List<WorkOrdDetail>();
  3495. if (moList.Any())
  3496. {
  3497. //同步工单
  3498. CreateWorkOrdDates(moList, moentryList, routingOps, workOrdSave, workOrdRoutingSave, workOrdDetails, new List<b_examine_result>(), new List<b_bom_child_examine>());
  3499. }
  3500. if (workOrdSave.Any())
  3501. {
  3502. await _businessDbContext.AddRangeAsync(workOrdSave);
  3503. //CalcPriority(input.factory_id.ToString());
  3504. RefreshPriority(null, input.factory_id.ToString());
  3505. }
  3506. var DBworkOrdList = _workOrdMaster.Select(a => workOrdSave.Count > 0 && a.Domain == workOrdSave[0].Domain && workOrdSave.Select(c => c.WorkOrd).Contains(a.WorkOrd));
  3507. if (workOrdRoutingSave.Any())
  3508. {
  3509. workOrdRoutingSave.ForEach(c =>
  3510. {
  3511. c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
  3512. });
  3513. await _businessDbContext.AddRangeAsync(workOrdRoutingSave);
  3514. }
  3515. if (workOrdDetails.Any())
  3516. {
  3517. workOrdDetails.ForEach(c =>
  3518. {
  3519. c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
  3520. });
  3521. await _businessDbContext.AddRangeAsync(workOrdDetails);
  3522. }
  3523. //2024/01/10:卫亮工单需求对齐采购需求,取所有未下达的工单做资源检查(排除年度中间件工单)
  3524. var moListCheck = _mysql_mes_morder.GetListAsync(a => (a.morder_state == MorderEnum.Initial_state || string.IsNullOrEmpty(a.morder_state)) && a.factory_id == input.factory_id && string.IsNullOrEmpty(a.analogcalcversion) && a.parent_id == null).Result;
  3525. var moEntryListCheck = _mysql_mes_moentry.GetListAsync(a => moListCheck.Select(b => b.morder_no).ToList().Contains(a.moentry_mono) && a.factory_id == input.factory_id).Result;
  3526. ////删除子料工单
  3527. //var deletedOrderList = _mysql_mes_morder.GetListAsync(a => moListCheck.Select(b => b.Id).ToList().Contains(a.parent_id.GetValueOrDefault()) && a.parent_id!=null && a.factory_id == input.factory_id && (a.morder_state == MorderEnum.Initial_state || string.IsNullOrEmpty(a.morder_state))).Result;
  3528. //var workOrderDelete = deletedOrderList.Select(b => b.morder_no).ToList();
  3529. //var deletedIds = deletedOrderList.Select(a => a.Id).ToList();
  3530. //var qrwork = _workOrdMaster.Select(a => workOrderDelete.Contains(a.WorkOrd) && (string.IsNullOrEmpty(a.Status) || a.Status.ToLower() == "p") && a.Domain == input.factory_id.ToString()).ToList();
  3531. //workOrderDelete = qrwork.Select(q => q.WorkOrd).ToList();
  3532. //_workOrdMaster.Delete(a => workOrderDelete.Contains(a.WorkOrd) && a.Domain == input.factory_id.ToString());
  3533. //_workOrdRouting.Delete(a => workOrderDelete.Contains(a.WorkOrd) && a.Domain == input.factory_id.ToString());
  3534. //_workOrdDetail.Delete(a => workOrderDelete.Contains(a.WorkOrd) && a.Domain == input.factory_id.ToString());
  3535. //await _mysql_mes_morder.HardDeleteAsync(deletedOrderList);
  3536. //var deletedEntryList = _mysql_mes_moentry.GetListAsync(a => workOrderDelete.Contains(a.moentry_mono) && a.factory_id == input.factory_id).Result;
  3537. //await _mysql_mes_moentry.HardDeleteAsync(deletedEntryList);
  3538. //var examine_result = _mysql_examine_result.GetListAsync(a => workOrderDelete.Contains(a.morder_no) && a.factory_id == input.factory_id).Result;
  3539. //List<srm_po_occupy> occupy = await _mysql_srm_po_occupy.GetListAsync(s => workOrderDelete.Contains(s.morder_mo));
  3540. //_businessDbContext.BulkDelete(occupy);
  3541. ////清理工单占用
  3542. //List<mes_mooccupy> mooccupy = await _mysql_mes_mooccupy.GetListAsync(s => deletedIds.Contains(s.moo_id.GetValueOrDefault()));
  3543. //if (mooccupy.Any())
  3544. //{
  3545. // _businessDbContext.BulkDelete(mooccupy);
  3546. //}
  3547. ////清理掉库存占用
  3548. //var itemstockoccupy = _mysql_ic_item_stockoccupy.GetListAsync(s => workOrderDelete.Contains(s.morder_mo)).Result;
  3549. //if (itemstockoccupy.Any())
  3550. //{
  3551. // _businessDbContext.BulkDelete(itemstockoccupy);
  3552. //}
  3553. //await _mysql_bom_child_examine.HardDeleteAsync(a => examine_result.Select(b => b.Id).ToList().Contains(a.examine_id.Value) && a.factory_id == input.factory_id);
  3554. //await _mysql_examine_result.HardDeleteAsync(examine_result);
  3555. await _businessBangDbContext.SaveChangesAsync();
  3556. await PlanOrderResourceCheck(moListCheck.OrderBy(a => a.moentry_sys_stime).ToList(), moEntryListCheck, bang_id, "", false, true);
  3557. var examine_resultList = _mysql_examine_result.GetListAsync(a => a.bangid == bang_id).Result;
  3558. var weekplanList = _replenishmentWeekPlan.GetListAsync(a => moListCheck.Select(b => b.morder_no).ToList().Contains(a.ProductionOrder) && a.IsReplenishmentModel == "N" && a.factory_id == input.factory_id).Result;
  3559. weekplanList.ForEach(a =>
  3560. {
  3561. var moItem = examine_resultList.Find(b => b.morder_no == a.ProductionOrder);
  3562. List<RoutingOpDetail> routingOp = routingOps.Where(x => x.RoutingCode == a.ItemNumber).ToList();
  3563. //组装标准工时
  3564. var Assembly = routingOp.Where(x => x.Ufld1 == "组装" && x.MilestoneOp).FirstOrDefault();
  3565. //热封标准工时
  3566. var HeatSealing = routingOp.Where(x => x.Ufld1 == "热封" && x.MilestoneOp).FirstOrDefault();
  3567. //包装标准工时
  3568. var Packaging = routingOp.Where(x => x.Ufld1 == "包装" && x.MilestoneOp).FirstOrDefault();
  3569. if (moItem != null)
  3570. {
  3571. if (moItem.kitting_times < a.PlanStartDate)
  3572. {
  3573. a.ItemStatus = "齐套";
  3574. a.PlanKittingDate = moItem.kitting_times;
  3575. a.AssembleHours = Assembly == null ? 0 : Assembly.RunTime * a.Qty;
  3576. a.HeatSealHours = HeatSealing == null ? 0 : HeatSealing.RunTime * a.Qty;
  3577. a.PackageHours = Packaging == null ? 0 : Packaging.RunTime * a.Qty;
  3578. a.TotalHours = a.AssembleHours + a.HeatSealHours + a.PackageHours;
  3579. }
  3580. else
  3581. {
  3582. a.ItemStatus = "欠料";
  3583. a.PlanKittingDate = moItem.kitting_times;
  3584. a.AssembleHours = Assembly == null ? 0 : Assembly.RunTime * a.Qty;
  3585. a.HeatSealHours = HeatSealing == null ? 0 : HeatSealing.RunTime * a.Qty;
  3586. a.PackageHours = Packaging == null ? 0 : Packaging.RunTime * a.Qty;
  3587. a.TotalHours = a.AssembleHours + a.HeatSealHours + a.PackageHours;
  3588. }
  3589. }
  3590. });
  3591. _businessDbContext.UpdateRange(weekplanList);
  3592. await _businessBangDbContext.SaveChangesAsync();
  3593. return "OK";
  3594. }
  3595. private DateTime GetNextMonday()
  3596. {
  3597. var preSunday = DateTime.Now.AddDays(0 - (int)DateTime.Now.DayOfWeek);//上周日
  3598. return Convert.ToDateTime(preSunday.AddDays(8).ToString("yyyy-MM-dd 00:00:00.000"));////上周日加八天即为下周一
  3599. }
  3600. public static int WeekOfMonth(DateTime day, int WeekStart)
  3601. {
  3602. //WeekStart
  3603. //1表示 周一至周日 为一周
  3604. //2表示 周日至周六 为一周
  3605. DateTime FirstofMonth;
  3606. FirstofMonth = Convert.ToDateTime(day.Date.Year + "-" + day.Date.Month + "-" + 1);
  3607. int i = (int)FirstofMonth.Date.DayOfWeek;
  3608. if (i == 0)
  3609. {
  3610. i = 7;
  3611. }
  3612. if (WeekStart == 1)
  3613. {
  3614. return (day.Date.Day + i - 2) / 7 + 1;
  3615. }
  3616. if (WeekStart == 2)
  3617. {
  3618. return (day.Date.Day + i - 1) / 7;
  3619. }
  3620. return 0;
  3621. //错误返回值0
  3622. }
  3623. private async Task ClearDO(string domain)
  3624. {
  3625. var purordlist = _PurOrdMaster.Select(x => x.Status.ToUpper() != "C" && x.ReqBy == "DO" && x.Domain == domain && x.USAGE != "ECR" && x.USAGE != "研发").ToList();
  3626. var purdtllist = _PurOrdDetail.Select(x => purordlist.Select(c => c.RecID).Contains(x.PurOrdRecID) && x.Domain == domain).ToList();
  3627. var shdzblist = _scm_shdzb.Select(x => purordlist.Select(c => c.PurOrd).Contains(x.po_bill)).ToList();
  3628. var podslist = _srmpolistds.Select(x => purordlist.Select(c => c.PurOrd).Contains(x.ponumber) && x.isactive == 1).ToList();
  3629. List<PurOrdMaster> delMstlist = new List<PurOrdMaster>();
  3630. List<PurOrdDetail> delDtllist = new List<PurOrdDetail>();
  3631. List<PurOrdDetail> mstdtl = new List<PurOrdDetail>();
  3632. int rctqtyCount;
  3633. int shdzbCount;
  3634. int dsCount;
  3635. bool isDel;
  3636. foreach (var mst in purordlist)
  3637. {
  3638. rctqtyCount = 0;
  3639. shdzbCount = 0;
  3640. dsCount = 0;
  3641. mstdtl = purdtllist.Where(x => x.PurOrdRecID == mst.RecID).ToList();
  3642. if (mstdtl.Any())
  3643. {
  3644. foreach (var dtl in mstdtl)
  3645. {
  3646. isDel = true;
  3647. if (dtl.RctQty > 0)//有收货数量
  3648. {
  3649. rctqtyCount++;
  3650. isDel = false;
  3651. }
  3652. if (shdzblist.Exists(x => x.po_bill == mst.PurOrd && x.sh_material_code == dtl.ItemNum && x.po_billline == dtl.Line.ToString()))//有发货
  3653. {
  3654. shdzbCount++;
  3655. isDel = false;
  3656. }
  3657. if (podslist.Exists(x => x.ponumber == mst.PurOrd && x.itemnum == dtl.ItemNum && x.poline == dtl.Line && ((x.status.ToUpper() != "C" && x.schedqty > 0) || (x.status.ToUpper() == "C" && x.sentqty > 0))))//非关闭但是有需求数量或已关闭但是有已交数量 则有交货单
  3658. {
  3659. dsCount++;
  3660. isDel = false;
  3661. }
  3662. if (isDel)
  3663. {
  3664. delDtllist.Add(dtl);
  3665. }
  3666. }
  3667. //没有关联记录,则删除
  3668. if (rctqtyCount == 0 && shdzbCount == 0 && dsCount == 0)
  3669. {
  3670. delMstlist.Add(mst);
  3671. }
  3672. }
  3673. else
  3674. {
  3675. delMstlist.Add(mst);
  3676. }
  3677. }
  3678. //通过要删除的要货令明细,删除采购申请,然后根据删除的采购申请,删除srm_po_list
  3679. var delpolist = _mysql_srm_po_main.GetListAsync(x => delMstlist.Select(c => c.PurOrd).Contains(x.po_billno) && x.factory_id.ToString() == domain).Result;
  3680. var podtllist = _mysql_srm_po_list.GetListAsync(x => delDtllist.Select(c => c.PurOrd).Contains(x.po_billno) && x.factory_id.ToString() == domain).Result;
  3681. List<srm_po_list> delpllist = new List<srm_po_list>();
  3682. foreach (var pl in podtllist)
  3683. {
  3684. if (delDtllist.Exists(x => x.PurOrd == pl.po_billno && x.ItemNum == pl.ItemNum && x.Line == pl.polist_row.GetValueOrDefault()))
  3685. {
  3686. delpllist.Add(pl);
  3687. }
  3688. }
  3689. var delocclist = _mysql_srm_po_occupy.GetListAsync(x => delpllist.Select(c => c.Id).Contains(x.polist_id.GetValueOrDefault())).Result;
  3690. var delprlist = _mysql_srm_pr_main.GetListAsync(x => delpllist.Select(c => c.pr_id).Contains(x.Id)).Result;
  3691. using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
  3692. {
  3693. try
  3694. {
  3695. _businessDbContext.BulkDelete(delMstlist);
  3696. _businessDbContext.BulkDelete(delDtllist);
  3697. _businessDbContext.BulkDelete(delpolist);
  3698. _businessDbContext.BulkDelete(delpllist);
  3699. _businessDbContext.BulkDelete(delocclist);
  3700. _businessDbContext.BulkDelete(delprlist);
  3701. await unitOfWork.CompleteAsync();
  3702. }
  3703. catch (Exception e)
  3704. {
  3705. unitOfWork.Dispose();
  3706. new NLogHelper("ClearDO").WriteLog("ClearDO", "清除要货令失败:" + e.Message, _currentTenant.Id.ToString());
  3707. }
  3708. }
  3709. }
  3710. /// <summary>
  3711. /// 根据标准工艺获取生产时长(天)
  3712. /// </summary>
  3713. /// <param name="param"></param>
  3714. /// <returns></returns>
  3715. public int ProductTime(List<RoutingOpDetail> routingOps, string ItemNum, string Domain, decimal QtyOrd)
  3716. {
  3717. var allOps = routingOps.Where(s => s.RoutingCode == ItemNum && s.Domain == Domain).ToList();
  3718. if (allOps.Any())
  3719. {
  3720. decimal maxRt = allOps.Max(s => s.RunTime);
  3721. decimal sumRt = allOps.Sum(s => s.RunTime);
  3722. decimal totalTime = (QtyOrd - 1) * maxRt + sumRt;//总计生产小时
  3723. return (int)(Math.Ceiling(totalTime / 8));
  3724. }
  3725. return 1;
  3726. }
  3727. /// <summary>
  3728. /// 发布周计划
  3729. /// </summary>
  3730. /// <param name="input"></param>
  3731. /// <returns></returns>
  3732. public async Task<string> PublishWeekPlan(InputDto input)
  3733. {
  3734. //默认发布未来四周工单
  3735. //主工单发布,子工单需要一起发布
  3736. var weekPlan = _replenishmentWeekPlan.GetListAsync(a => a.PlanStartDate > DateTime.Now.AddDays(-1) && a.PlanStartDate < DateTime.Now.AddDays(29) && a.IsReplenishmentModel == "N" && string.IsNullOrEmpty(a.ProductionStatus)).Result.OrderBy(a => a.Priority).ToList();
  3737. List<mes_morder> mes_Morders = _mysql_mes_morder.GetListAsync(a => weekPlan.Select(p => p.ProductionOrder).ToList().Contains(a.morder_no) && a.factory_id == input.factory_id).Result;
  3738. if (mes_Morders != null && mes_Morders.Count > 0)
  3739. {
  3740. List<mes_morder> mes_Morders_sub = _mysql_mes_morder.GetListAsync(a => mes_Morders.Select(p => p.Id).ToList().Contains(a.parent_id.GetValueOrDefault()) && a.factory_id == input.factory_id).Result;
  3741. if (mes_Morders_sub != null && mes_Morders_sub.Count > 0)
  3742. {
  3743. mes_Morders.AddRange(mes_Morders_sub);
  3744. }
  3745. }
  3746. List<WorkOrdMaster> workMasters = _workOrdMaster.Select(a => mes_Morders.Select(m => m.morder_no).ToList().Contains(a.WorkOrd) && a.Domain == input.factory_id.ToString());
  3747. for (int i = 0; i < weekPlan.Count; i++)
  3748. {
  3749. weekPlan[i].ProductionStatus = "已发布";
  3750. workMasters.ForEach(b =>
  3751. {
  3752. if (b.ItemNum == weekPlan[i].ItemNumber && b.WorkOrd == weekPlan[i].ProductionOrder)
  3753. {
  3754. b.Status = "p";
  3755. }
  3756. });
  3757. mes_Morders.ForEach(c =>
  3758. {
  3759. c.morder_state = MorderEnum.Initial_state;
  3760. });
  3761. }
  3762. _workOrdMaster.Update(workMasters);
  3763. _businessDbContext.UpdateRange(mes_Morders);
  3764. _businessDbContext.UpdateRange(weekPlan);
  3765. return "OK";
  3766. }
  3767. /// <summary>
  3768. /// 勾选发布周计划
  3769. /// </summary>
  3770. /// <param name="input"></param>
  3771. /// <returns></returns>
  3772. public async Task<string> SelectPublishWeekPlan(string ids, string factoryid)
  3773. {
  3774. List<long> idList = AnalysisIdList(ids);
  3775. //主工单发布,子工单需要一起发布
  3776. var weekPlan = _replenishmentWeekPlan.GetListAsync(a => idList.Contains(a.Id) && a.IsReplenishmentModel == "N" && string.IsNullOrEmpty(a.ProductionStatus) && a.factory_id.ToString() == factoryid).Result.OrderBy(a => a.Priority).ToList();
  3777. List<mes_morder> mes_Morders = _mysql_mes_morder.GetListAsync(a => weekPlan.Select(p => p.ProductionOrder).ToList().Contains(a.morder_no) && a.factory_id.ToString() == factoryid).Result;
  3778. if (mes_Morders != null && mes_Morders.Count > 0)
  3779. {
  3780. List<mes_morder> mes_Morders_sub = _mysql_mes_morder.GetListAsync(a => mes_Morders.Select(p => p.Id).ToList().Contains(a.parent_id.GetValueOrDefault()) && a.factory_id.ToString() == factoryid).Result;
  3781. if (mes_Morders_sub != null && mes_Morders_sub.Count > 0)
  3782. {
  3783. mes_Morders.AddRange(mes_Morders_sub);
  3784. }
  3785. }
  3786. List<WorkOrdMaster> workMasters = _workOrdMaster.Select(a => mes_Morders.Select(m => m.morder_no).ToList().Contains(a.WorkOrd) && a.Domain == factoryid);
  3787. for (int i = 0; i < weekPlan.Count; i++)
  3788. {
  3789. weekPlan[i].ProductionStatus = "已发布";
  3790. workMasters.ForEach(b =>
  3791. {
  3792. if (b.ItemNum == weekPlan[i].ItemNumber && b.WorkOrd == weekPlan[i].ProductionOrder)
  3793. {
  3794. b.Status = "p";
  3795. }
  3796. });
  3797. mes_Morders.ForEach(c =>
  3798. {
  3799. c.morder_state = MorderEnum.Initial_state;
  3800. });
  3801. }
  3802. //发布计划订单产生的工单
  3803. List<mes_morder> planMo = _mysql_mes_morder.GetListAsync(a => idList.Contains(a.Id) && string.IsNullOrEmpty(a.morder_state) && a.factory_id.ToString() == factoryid).Result;
  3804. if (planMo != null)
  3805. {
  3806. List<mes_morder> mes_Morders_child = _mysql_mes_morder.GetListAsync(a => planMo.Select(p => p.Id).ToList().Contains(a.parent_id.GetValueOrDefault()) && a.factory_id.ToString() == factoryid).Result;
  3807. if (mes_Morders_child != null && mes_Morders_child.Count > 0)
  3808. {
  3809. planMo.AddRange(mes_Morders_child);
  3810. }
  3811. List<WorkOrdMaster> planwork = _workOrdMaster.Select(a => planMo.Select(m => m.morder_no).ToList().Contains(a.WorkOrd) && a.Domain == factoryid);
  3812. planMo.ForEach(c =>
  3813. {
  3814. c.morder_state = MorderEnum.Initial_state;
  3815. });
  3816. planwork.ForEach(b =>
  3817. {
  3818. b.Status = "p";
  3819. });
  3820. workMasters.AddRange(planwork);
  3821. mes_Morders.AddRange(planMo);
  3822. }
  3823. _workOrdMaster.Update(workMasters);
  3824. _businessDbContext.UpdateRange(mes_Morders);
  3825. _businessDbContext.UpdateRange(weekPlan);
  3826. return "OK";
  3827. }
  3828. private List<long> AnalysisIdList(string ids)
  3829. {
  3830. if (string.IsNullOrEmpty(ids))
  3831. {
  3832. throw new NotImplementedException("传入参数不正确,请选择");
  3833. }
  3834. Array alist = ids.Split(',');
  3835. List<long> idList = new List<long>();
  3836. foreach (string longid in alist)
  3837. {
  3838. idList.Add(long.Parse(longid));
  3839. }
  3840. return idList;
  3841. }
  3842. /// <summary>
  3843. /// 每天补货
  3844. /// </summary>
  3845. /// <param name="input"></param>
  3846. /// <returns></returns>
  3847. public async Task<string> CalcDayPlan(InputDto input)
  3848. {
  3849. input.year = DateTime.Now.Year;
  3850. input.month = DateTime.Now.Month;
  3851. ReplenishmentDto replenishmentDto = GetROPParam(input.factory_id.ToString());
  3852. //DOP运行资源检查每个成品和半成品SKU的可用库存,当可用库存 <= 修正后ROP时,自动生成月度计划订单(MPlan order,MPO48年月日3位流水号)= EOP;可用库存为没有被其他SO和PO占用的(合格成品或半成品库存 + WIP);
  3853. string planMonthQuery = $"{DateTime.Now.Year}-{DateTime.Now.Month.ToString("00")}";
  3854. var ropModelList = _replenishmentROPWeekPlan.GetListAsync(a => a.planmonth == planMonthQuery && a.erp_cls == 1 && a.distributionchannel == "瑞奇" && a.factory_id == input.factory_id && !a.IsDeleted).Result;
  3855. List<string> planItemList = ropModelList?.Select(a => a.number).Distinct().ToList();
  3856. var itemList = _mysql_ic_item.GetListAsync(a => planItemList.Contains(a.number) && !a.IsDeleted).Result;
  3857. //获取BOM用于分解到原材料
  3858. var boms = _ic_bom.GetListAsync(a => ropModelList.Select(p => p.number).ToList().Contains(a.item_number) && a.factory_id == input.factory_id).Result;
  3859. var pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
  3860. List<mo_ic_bom> autoCreates = new List<mo_ic_bom>();
  3861. boms.ForEach(p =>
  3862. {
  3863. if (!pretreatments.Where(s => s.sourceid == p.mysql_id).Any())
  3864. {
  3865. autoCreates.Add(p);
  3866. }
  3867. });
  3868. if (autoCreates.Any())
  3869. {
  3870. AutoCreateBomBill(input.company_id.ToString(), autoCreates);
  3871. pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
  3872. }
  3873. var itemStock = CalcStock(ropModelList.Select(a => a.number).Distinct().ToList(), input);
  3874. var bomList = _ic_bom.GetListAsync(a => ropModelList.Select(a => a.number).ToList().Contains(a.item_number) && !a.IsDeleted && a.factory_id == input.factory_id).Result;
  3875. List<mes_morder> moList = new List<mes_morder>();
  3876. List<mes_moentry> moentryList = new List<mes_moentry>();
  3877. List<string> planMonthList = new List<string>();
  3878. for (int j = 0; j < replenishmentDto.SaleFcstMonth + 3; j++)
  3879. {
  3880. string itemMonth = $"{DateTime.Now.AddMonths(j).Year}-{DateTime.Now.AddMonths(j).Month.ToString("00")}";
  3881. planMonthList.Add(itemMonth);
  3882. }
  3883. planMonthList.Sort();
  3884. //获取周生产计划
  3885. var WeekPlanList = _replenishmentWeekPlan.GetListAsync(a => ropModelList.Select(b => b.number).ToList().Contains(a.ItemNumber) && a.IsReplenishmentModel == "N" && planMonthList.Contains(a.PlanMonth)).Result;
  3886. var workOrdMasterList = _workOrdMaster.Select(s => WeekPlanList.Select(a => a.ProductionOrder).ToList().Contains(s.WorkOrd) && s.Domain == input.factory_id.ToString());
  3887. var workOrdDetailList = _workOrdDetail.Select(s => WeekPlanList.Select(a => a.ProductionOrder).ToList().Contains(s.WorkOrd) && s.Domain == input.factory_id.ToString());
  3888. var workOrdRoutingList = _workOrdRouting.Select(s => WeekPlanList.Select(a => a.ProductionOrder).ToList().Contains(s.WorkOrd) && s.Domain == input.factory_id.ToString());
  3889. var mesmorderList = _mysql_mes_morder.GetListAsync(s => WeekPlanList.Select(a => a.ProductionOrder).ToList().Contains(s.morder_no) && s.factory_id == input.factory_id).Result;
  3890. var mesmorderEntryList = _mysql_mes_moentry.GetListAsync(s => WeekPlanList.Select(a => a.ProductionOrder).ToList().Contains(s.moentry_mono) && s.factory_id == input.factory_id).Result;
  3891. //扣减需要删除周生产计划
  3892. List<ReplenishmentWeekPlan> deleteList = new List<ReplenishmentWeekPlan>();
  3893. //扣减需要更新周生产计划
  3894. List<ReplenishmentWeekPlan> updateList = new List<ReplenishmentWeekPlan>();
  3895. //减货
  3896. ropModelList.ForEach(a =>
  3897. {
  3898. //超出最高库存,优先扣减日期最近未发布的周生计划数量和对应的计划工单的数量
  3899. if (itemStock.First(c => c.ItemNumber == a.number).Qty > a.max_stock_level)
  3900. {
  3901. decimal? Qty = itemStock.First(c => c.ItemNumber == a.number).Qty - a.max_stock_level;
  3902. var itemWeekPlan = WeekPlanList.FindAll(b => b.ItemNumber == a.number);
  3903. //如果没找到周生成计划,那没法扣减,理论上不会出现这种数据场景
  3904. if (itemWeekPlan != null && itemWeekPlan.Count > 0)
  3905. {
  3906. itemWeekPlan.OrderBy(a => a.Year).ThenBy(b => b.Month).ThenBy(c => c.Week).ThenBy(d => d.WeekSeq);
  3907. for (int i = 0; i < itemWeekPlan.Count; i++)
  3908. {
  3909. if (itemWeekPlan[i].ProductionStatus != "已发布")
  3910. {
  3911. if (itemWeekPlan[i].Qty <= Qty)
  3912. {
  3913. deleteList.Add(itemWeekPlan[i]);
  3914. Qty = Qty - itemWeekPlan[i].Qty;
  3915. }
  3916. else
  3917. {
  3918. itemWeekPlan[i].Qty = itemWeekPlan[i].Qty - Qty.GetValueOrDefault();
  3919. updateList.Add(itemWeekPlan[i]);
  3920. break;
  3921. }
  3922. }
  3923. }
  3924. }
  3925. }
  3926. });
  3927. if (deleteList.Count > 0)
  3928. {
  3929. await _businessDbContext.BulkDeleteAsync(deleteList);
  3930. _workOrdMaster.Delete(workOrdMasterList.Where(a => deleteList.Select(b => b.ProductionOrder).ToList().Contains(a.WorkOrd)).ToList());
  3931. _workOrdDetail.Delete(workOrdDetailList.Where(a => deleteList.Select(b => b.ProductionOrder).ToList().Contains(a.WorkOrd)).ToList());
  3932. _workOrdRouting.Delete(workOrdRoutingList.Where(a => deleteList.Select(b => b.ProductionOrder).ToList().Contains(a.WorkOrd)).ToList());
  3933. await _businessDbContext.BulkDeleteAsync(mesmorderList.Where(a => deleteList.Select(b => b.ProductionOrder).ToList().Contains(a.morder_no)).ToList());
  3934. await _businessDbContext.BulkDeleteAsync(mesmorderEntryList.Where(a => deleteList.Select(b => b.ProductionOrder).ToList().Contains(a.moentry_mono)).ToList());
  3935. }
  3936. if (updateList.Count > 0)
  3937. {
  3938. _businessDbContext.UpdateRange(updateList);
  3939. List<WorkOrdMaster> itemUpdate = new List<WorkOrdMaster>();
  3940. List<WorkOrdDetail> itemDetailUpdate = new List<WorkOrdDetail>();
  3941. List<WorkOrdRouting> itemRoutingUpdate = new List<WorkOrdRouting>();
  3942. List<mes_morder> itemMesmorderList = new List<mes_morder>();
  3943. List<mes_moentry> itemMesmorderEntryList = new List<mes_moentry>();
  3944. foreach (var item in updateList)
  3945. {
  3946. var workItem = workOrdMasterList.Find(a => a.ItemNum == item.ItemNumber && a.WorkOrd == item.ProductionOrder);
  3947. workItem.QtyOrded = item.Qty;
  3948. var workDetailItem = workOrdDetailList.Find(a => a.ItemNum == item.ItemNumber && a.WorkOrd == item.ProductionOrder);
  3949. workDetailItem.QtyRequired = item.Qty;
  3950. var workOrderItem = mesmorderList.Find(a => a.product_code == item.ItemNumber && a.morder_no == item.ProductionOrder);
  3951. workOrderItem.need_number = item.Qty;
  3952. workOrderItem.morder_production_number = item.Qty;
  3953. var workOrdEntryItem = mesmorderEntryList.Find(a => a.moentry_mono == item.ProductionOrder);
  3954. workOrdEntryItem.need_number = item.Qty;
  3955. workOrdEntryItem.morder_production_number = item.Qty;
  3956. itemUpdate.Add(workItem);
  3957. itemDetailUpdate.Add(workDetailItem);
  3958. itemMesmorderList.Add(workOrderItem);
  3959. itemMesmorderEntryList.Add(workOrdEntryItem);
  3960. var planBOM = boms.Find(b => b.item_number == item.ItemNumber);
  3961. var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList();
  3962. var returnlist = ObjectMapper.Map<List<b_bom_pretreatment>, List<BomChildExamineDto>>(pretreament);
  3963. returnlist = returnlist.OrderBy(s => s.num_order).ToList();
  3964. var level1Dto = returnlist[0];
  3965. level1Dto.qty = item.Qty;
  3966. CaclMaterialShortage(returnlist);
  3967. foreach (var child in returnlist)
  3968. {
  3969. var itemWorkOrdRoutingList = workOrdRoutingList.FindAll(w => w.WorkOrd == item.ProductionOrder);
  3970. if (itemWorkOrdRoutingList != null && itemWorkOrdRoutingList.Count > 0)
  3971. {
  3972. foreach (var r in itemWorkOrdRoutingList)
  3973. {
  3974. if (r.ItemNum == child.item_number)
  3975. {
  3976. r.QtyOrded = child.needCount;
  3977. itemRoutingUpdate.Add(r);
  3978. }
  3979. }
  3980. }
  3981. }
  3982. }
  3983. _workOrdMaster.Update(itemUpdate);
  3984. _workOrdDetail.Update(itemDetailUpdate);
  3985. _workOrdRouting.Update(itemRoutingUpdate);
  3986. _businessDbContext.UpdateRange(itemMesmorderList);
  3987. _businessDbContext.UpdateRange(itemMesmorderEntryList);
  3988. }
  3989. //补货
  3990. List<ReplenishmentWeekPlan> weekPlanAdd = new List<ReplenishmentWeekPlan>();
  3991. List<RoutingOpDetail> routingOps = _routingOpDetail.Select(p => planItemList.Contains(p.RoutingCode) && p.Domain == input.factory_id.ToString() && p.IsActive);
  3992. long bang_id = help.NextId();
  3993. ropModelList.ForEach(a =>
  3994. {
  3995. //低于安全库存,优先调整日期最近未发布的周生计划数量和对应的计划工单的数量
  3996. if (itemStock.First(c => c.ItemNumber == a.number).Qty < a.security_stock)
  3997. {
  3998. decimal? Qty = a.max_stock_level - itemStock.First(c => c.ItemNumber == a.number).Qty;
  3999. var itemWeekPlan = WeekPlanList.FindAll(b => b.ItemNumber == a.number);
  4000. //如果没找到周生成计划,那没法扣减,理论上不会出现这种数据场景
  4001. if (itemWeekPlan != null && itemWeekPlan.Count > 0)
  4002. {
  4003. itemWeekPlan.OrderBy(a => a.Year).ThenBy(b => b.Month).ThenBy(c => c.Week).ThenBy(d => d.WeekSeq);
  4004. for (int i = 0; i < itemWeekPlan.Count; i++)
  4005. {
  4006. if (itemWeekPlan[i].ProductionStatus != "已发布")
  4007. {
  4008. itemWeekPlan[i].Qty = itemWeekPlan[i].Qty + Qty.GetValueOrDefault();
  4009. weekPlanAdd.Add(itemWeekPlan[i]);
  4010. }
  4011. }
  4012. }
  4013. }
  4014. });
  4015. if (weekPlanAdd.Count > 0)
  4016. {
  4017. await _businessDbContext.AddRangeAsync(weekPlanAdd);
  4018. List<WorkOrdMaster> itemUpdate = new List<WorkOrdMaster>();
  4019. List<WorkOrdDetail> itemDetailUpdate = new List<WorkOrdDetail>();
  4020. List<WorkOrdRouting> itemRoutingUpdate = new List<WorkOrdRouting>();
  4021. List<mes_morder> itemMesmorderList = new List<mes_morder>();
  4022. List<mes_moentry> itemMesmorderEntryList = new List<mes_moentry>();
  4023. foreach (var item in weekPlanAdd)
  4024. {
  4025. var workItem = workOrdMasterList.Find(a => a.ItemNum == item.ItemNumber && a.WorkOrd == item.ProductionOrder);
  4026. workItem.QtyOrded = item.Qty;
  4027. var workDetailItem = workOrdDetailList.Find(a => a.ItemNum == item.ItemNumber && a.WorkOrd == item.ProductionOrder);
  4028. workDetailItem.QtyRequired = item.Qty;
  4029. var workOrderItem = mesmorderList.Find(a => a.product_code == item.ItemNumber && a.morder_no == item.ProductionOrder);
  4030. workOrderItem.need_number = item.Qty;
  4031. workOrderItem.morder_production_number = item.Qty;
  4032. var workOrdEntryItem = mesmorderEntryList.Find(a => a.moentry_mono == item.ProductionOrder);
  4033. workOrdEntryItem.need_number = item.Qty;
  4034. workOrdEntryItem.morder_production_number = item.Qty;
  4035. itemUpdate.Add(workItem);
  4036. itemDetailUpdate.Add(workDetailItem);
  4037. itemMesmorderList.Add(workOrderItem);
  4038. itemMesmorderEntryList.Add(workOrdEntryItem);
  4039. var planBOM = boms.Find(b => b.item_number == item.ItemNumber);
  4040. var pretreament = pretreatments.Where(c => c.sourceid == planBOM.mysql_id).ToList();
  4041. var returnlist = ObjectMapper.Map<List<b_bom_pretreatment>, List<BomChildExamineDto>>(pretreament);
  4042. returnlist = returnlist.OrderBy(s => s.num_order).ToList();
  4043. var level1Dto = returnlist[0];
  4044. level1Dto.qty = item.Qty;
  4045. CaclMaterialShortage(returnlist);
  4046. foreach (var child in returnlist)
  4047. {
  4048. var itemWorkOrdRoutingList = workOrdRoutingList.FindAll(w => w.WorkOrd == item.ProductionOrder);
  4049. if (itemWorkOrdRoutingList != null && itemWorkOrdRoutingList.Count > 0)
  4050. {
  4051. foreach (var r in itemWorkOrdRoutingList)
  4052. {
  4053. if (r.ItemNum == child.item_number)
  4054. {
  4055. r.QtyOrded = child.needCount;
  4056. itemRoutingUpdate.Add(r);
  4057. }
  4058. }
  4059. }
  4060. }
  4061. }
  4062. _workOrdMaster.Update(itemUpdate);
  4063. _workOrdDetail.Update(itemDetailUpdate);
  4064. _workOrdRouting.Update(itemRoutingUpdate);
  4065. _businessDbContext.UpdateRange(itemMesmorderList);
  4066. _businessDbContext.UpdateRange(itemMesmorderEntryList);
  4067. await _businessBangDbContext.SaveChangesAsync();
  4068. }
  4069. //DOP运行资源检查每个原材料SKU的可用库存,当可用库存<=修正后ROP时,自动生成月度采购申请(Purchase request,PR46年月日4位流水号)=EOP;可用库存为没有被其他SO和PO占用的(合格原材料库存+在途库存);
  4070. var ropMaterialModelList = _replenishmentROPWeekPlan.GetListAsync(a => a.planmonth == planMonthQuery && a.erp_cls == 3 && a.distributionchannel == "瑞奇" && a.factory_id == input.factory_id && !a.IsDeleted).Result;
  4071. List<srm_pr_main> prList = new List<srm_pr_main>();
  4072. var numbers = ropMaterialModelList.Where(a => a.erp_cls == 3).Select(b => b.number).ToList();
  4073. var icItemList = _mysql_ic_item.GetListAsync(c => numbers.Contains(c.number)).Result;
  4074. var srm_pr_mains = _srm_pr_main.GetListAsync(x => icItemList.Select(p => p.Id).ToList().Contains(x.icitem_id.Value) && x.state != 0 && !x.IsDeleted).Result;
  4075. var quarter_srm_pr_mains = srm_pr_mains.Where(s => s.pr_psend_date >= _CalcBomViewAppService.quarter_starttime && s.pr_psend_date < _CalcBomViewAppService.quarter_endtime).ToList();
  4076. var materialItemStock = _invMaster.Select(a => numbers.Contains(a.ItemNum) && a.Domain == input.factory_id.ToString());
  4077. //更新未确认未合并的PR
  4078. //占用的PR不能扣减
  4079. var prCanUpdateList = _mysql_srm_pr_main.GetListAsync(a => icItemList.Select(c => c.Id).ToList().Contains(a.icitem_id.GetValueOrDefault()) && a.pr_ssend_date >= DateTime.Now.Date.AddDays(1) && a.state == 1).Result;
  4080. var prIds = prCanUpdateList.Select(a => a.Id).ToList();
  4081. var prOccupy = _mysql_srm_po_occupy.GetListAsync(a => prIds.Contains(a.polist_id.GetValueOrDefault()) && a.factory_id == input.factory_id).Result;
  4082. var prOccupyIds = prOccupy.Select(a => a.polist_id).ToList();
  4083. prCanUpdateList = prCanUpdateList.Where(a => !prOccupyIds.Contains(a.Id)).ToList();
  4084. List<srm_pr_main> prUpdateList = new List<srm_pr_main>();
  4085. List<srm_pr_main> prDeleteList = new List<srm_pr_main>();
  4086. ropMaterialModelList.ForEach(b =>
  4087. {
  4088. var materialQty = materialItemStock?.Where(c => c.ItemNum == b.number && c.Location.StartsWith('1'));
  4089. decimal QtyStock = materialQty != null ? materialQty.Sum(c => c.AvailStatusQty.GetValueOrDefault() + c.Assay.GetValueOrDefault()) : 0;
  4090. if (QtyStock < b.security_stock)
  4091. {
  4092. mo_srm_purchase supplier = null;
  4093. var item = icItemList.Find(d => d.number == b.number);
  4094. var supplist = supplierList.Where(s => s.number == b.number).ToList();
  4095. decimal day = 0;
  4096. var plan_date = DateTime.Now.AddDays(1 + Convert.ToDouble(b.supply_leadtime));
  4097. //判断当前时间与交期还剩余多少天
  4098. var timesp = plan_date - DateTime.Now.Date;
  4099. //交期-生产时长-物料前处理周期
  4100. day = timesp.Days;
  4101. if (day > 0)
  4102. {
  4103. supplist = supplist.Where(s => s.lead_time.GetValueOrDefault() < day).ToList();
  4104. if (supplist.Any())
  4105. {
  4106. //TODO:走配额管理
  4107. List<mo_srm_pr_main> itemPrlist = quarter_srm_pr_mains.Where(s => s.icitem_id == item.Id).ToList();
  4108. if (itemPrlist.Any())
  4109. {
  4110. decimal qtyCount = itemPrlist.Sum(x => x.pr_aqty).GetValueOrDefault();
  4111. //按配额比例,计算使用哪个供应商。
  4112. List<PrPurchaseDto> PrPurchaseDtoList = new List<PrPurchaseDto>();
  4113. supplist.ForEach(s =>
  4114. {
  4115. PrPurchaseDto purDto = new PrPurchaseDto();
  4116. purDto.pr_purchaseid = s.supplier_id;
  4117. purDto.num = itemPrlist.Where(x => x.pr_purchaseid == s.supplier_id).Sum(c => c.pr_aqty.GetValueOrDefault());
  4118. purDto.ratio = Math.Round(purDto.num / qtyCount, 2, MidpointRounding.AwayFromZero);
  4119. purDto.quota_priority = s.quota_priority;
  4120. purDto.quota_rate = s.quota_rate.GetValueOrDefault();
  4121. PrPurchaseDtoList.Add(purDto);
  4122. });
  4123. //首先取出占比还小于配额比的数据
  4124. var priorityPurlist = PrPurchaseDtoList.Where(s => s.quota_rate - s.ratio > 2).ToList();
  4125. if (!priorityPurlist.Any())
  4126. {
  4127. //没有则取出当前集合中的供应商的数据,计算差额
  4128. priorityPurlist = PrPurchaseDtoList;
  4129. }
  4130. //还没有达到配额比的供应商,优先分配
  4131. decimal difference = 0;
  4132. PrPurchaseDto dto1 = priorityPurlist[0];
  4133. priorityPurlist.ForEach(s =>
  4134. {
  4135. decimal diff = s.quota_rate - s.ratio;
  4136. if (diff > difference)
  4137. {
  4138. difference = diff;
  4139. dto1 = s;
  4140. }
  4141. });
  4142. supplier = supplist.Find(s => s.supplier_id == dto1.pr_purchaseid);
  4143. }
  4144. else
  4145. {
  4146. supplier = supplist.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
  4147. }
  4148. }
  4149. else
  4150. {
  4151. supplier = supplist.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
  4152. }
  4153. }
  4154. else
  4155. {
  4156. supplier = supplist.OrderBy(s => s.quota_priority).FirstOrDefault();//默认取配额优先级
  4157. }
  4158. srm_pr_main srm_Pr = new srm_pr_main();
  4159. srm_Pr.GenerateNewId(help.NextId());
  4160. srm_Pr.IsRequireGoods = supplier.IsRequireGoods;
  4161. srm_Pr.pr_purchaseid = supplier.supplier_id;//供应商id
  4162. srm_Pr.pr_purchasenumber = supplier.supplier_number;//供应商编码
  4163. srm_Pr.pr_purchasename = supplier.supplier_name;//供应商名称
  4164. srm_Pr.pr_purchaser = supplier.order_rector_name;//采购员
  4165. srm_Pr.pr_purchaser_num = supplier.order_rector_num;//采购员工号(采购信息表)
  4166. //数量圆整 按最小包装量向上圆整
  4167. decimal qty = Math.Max(b.eop.Value, b.security_stock.GetValueOrDefault() - QtyStock);
  4168. //判断最小起订量
  4169. qty = qty > supplier.qty_min ? qty : supplier.qty_min.GetValueOrDefault();
  4170. srm_Pr.pr_rqty = qty;//需求数量
  4171. srm_Pr.pr_aqty = qty;//申请数量
  4172. srm_Pr.pr_sqty = qty;//建议数量
  4173. srm_Pr.icitem_id = item.Id;//物料id
  4174. srm_Pr.icitem_name = b.name;//物料名称
  4175. srm_Pr.pr_order_type = "1";//单据类型
  4176. srm_Pr.pr_ssend_date = DateTime.Now.Date.AddDays(1);//系统建议下单日期
  4177. srm_Pr.pr_sarrive_date = DateTime.Now.AddDays((double)supplier.lead_time.GetValueOrDefault());//系统建议到达日期(建议到货日期)
  4178. srm_Pr.pr_sysprice = supplier.order_price;//系统价格(含税)
  4179. srm_Pr.pr_orderprice = qty * supplier.order_price;//订单价格(含税)
  4180. srm_Pr.pr_price = supplier.netpurchase_price;//采购净价(不含税)
  4181. srm_Pr.pr_rate = supplier.taxrate;//税率
  4182. srm_Pr.pr_unit = item.unit;//单位
  4183. srm_Pr.state = 1;//状态
  4184. srm_Pr.old_apply_aqty = 0;//已申请数量
  4185. srm_Pr.pr_type = b.erp_cls;//申请类型
  4186. srm_Pr.currencytype = supplier.currency_type == null ? 1 : supplier.currency_type.Value;//币种
  4187. srm_Pr.secInv_ratio = item.secinv_ratio;//安全库存触发采购比例
  4188. srm_Pr.tenant_id = input.tenant_id;
  4189. srm_Pr.company_id = input.company_id;
  4190. srm_Pr.factory_id = input.factory_id;
  4191. srm_Pr.create_time = DateTime.Now;
  4192. srm_Pr.create_by_name = "admin";
  4193. srm_Pr.update_time = DateTime.Now;
  4194. srm_Pr.update_by_name = "admin";
  4195. prList.Add(srm_Pr);
  4196. }
  4197. else if (QtyStock > b.max_stock_level)
  4198. {
  4199. //扣减PR
  4200. var item = icItemList.Find(d => d.number == b.number);
  4201. var ItemPRList = prCanUpdateList.FindAll(a => a.icitem_id == item.Id);
  4202. if (ItemPRList.Any())
  4203. {
  4204. ItemPRList = ItemPRList.OrderBy(a => a.pr_ssend_date).ToList();
  4205. var supplist = supplierList.Where(s => s.number == b.number).ToList();
  4206. decimal? QtySub = b.max_stock_level - QtyStock;
  4207. for (int i = 0; i < ItemPRList.Count; i++)
  4208. {
  4209. if (QtySub > 0)
  4210. {
  4211. var supplier = supplist.Find(s => s.mysql_id == ItemPRList[i].pr_purchaseid);
  4212. //扣减的时候要不要考虑经济批量?
  4213. if (ItemPRList[i].pr_rqty < QtySub)
  4214. {
  4215. prDeleteList.Add(ItemPRList[i]);
  4216. QtySub = QtySub - ItemPRList[i].pr_rqty;
  4217. }
  4218. else
  4219. {
  4220. if (ItemPRList[i].pr_rqty > supplier.qty_min)
  4221. {
  4222. if (ItemPRList[i].pr_rqty - supplier.qty_min > QtySub)
  4223. {
  4224. ItemPRList[i].pr_rqty = ItemPRList[i].pr_rqty - QtySub;
  4225. prUpdateList.Add(ItemPRList[i]);
  4226. break;
  4227. }
  4228. else
  4229. {
  4230. QtySub = QtySub - (ItemPRList[i].pr_rqty - supplier.qty_min);
  4231. ItemPRList[i].pr_rqty = supplier.qty_min;
  4232. prUpdateList.Add(ItemPRList[i]);
  4233. }
  4234. }
  4235. }
  4236. }
  4237. }
  4238. }
  4239. }
  4240. });
  4241. _businessDbContext.UpdateRange(prUpdateList);
  4242. prList.ForEach(a =>
  4243. {
  4244. a.GenerateNewId(help.NextId());
  4245. });
  4246. await _businessDbContext.AddRangeAsync(prList);
  4247. await _businessBangDbContext.SaveChangesAsync();
  4248. return "OK";
  4249. }
  4250. /// <summary>
  4251. /// 同步工单等相关数据
  4252. /// </summary>
  4253. /// <param name="morders"></param>
  4254. /// <param name="allRoutings">工艺路线数据</param>
  4255. public void CreateWorkOrdDates(List<mes_morder> morders, List<mes_moentry> WriteMoentry, List<RoutingOpDetail> allRoutings, List<WorkOrdMaster> workOrds, List<WorkOrdRouting> workOrdRoutings, List<WorkOrdDetail> workOrdDetails, List<b_examine_result> exmResult, List<b_bom_child_examine> childExamineList)
  4256. {
  4257. //var IsActived = _AccountValidityAppService.IsActived();
  4258. //if (!IsActived)
  4259. //{
  4260. // return;
  4261. //}
  4262. //工单主表
  4263. WorkOrdMaster workOrd;
  4264. //工单工艺路线表
  4265. WorkOrdRouting woRouting;
  4266. //处理全局变量
  4267. param.factoryId = morders[0].factory_id.GetValueOrDefault();
  4268. List<string> orderCode = morders.Select(c => c.product_code).ToList();
  4269. var crmoList = _mysql_crm_seorder.GetListAsync(m => WriteMoentry.Select(s => s.fbill_no).ToList().Contains(m.bill_no) && !m.IsDeleted).Result;
  4270. var cust = _custMaster.Select(c => c.IsActive && c.Domain == param.factoryId.ToString() && crmoList.Select(m => m.custom_no).Contains(c.Cust)).ToList();
  4271. //成品虚拟件对应关系
  4272. var productOpList = _productStructureOp.Select(x => orderCode.Contains(x.ProductItem) && x.Domain == param.factoryId.ToString());
  4273. //获取物料主数据
  4274. List<ItemMaster> itemMasters = _itemMaster.Select(p => orderCode.Contains(p.ItemNum) && p.Domain == param.factoryId.ToString()).ToList();
  4275. foreach (var item in morders)
  4276. {
  4277. var moItem = exmResult.Find(b => b.morder_no == item.morder_no);
  4278. //添加工单数据
  4279. workOrd = new WorkOrdMaster();
  4280. workOrd.Domain = item.factory_id.ToString();
  4281. workOrd.OrdDate = item.moentry_sys_stime.GetValueOrDefault().Date;
  4282. workOrd.ReleaseDate = Convert.ToDateTime(item.moentry_sys_stime.GetValueOrDefault().ToString("u"));
  4283. workOrd.DueDate = item.moentry_sys_etime;
  4284. workOrd.WorkOrd = item.morder_no;
  4285. workOrd.ItemNum = item.product_code;//物料编码
  4286. workOrd.QtyOrded = item.need_number.GetValueOrDefault();
  4287. workOrd.Period = 1;
  4288. workOrd.Priority = item.urgent;
  4289. workOrd.Status = "";
  4290. workOrd.IsActive = true;
  4291. workOrd.IsConfirm = true;
  4292. var curItem = itemMasters.FirstOrDefault(p => p.ItemNum == item.product_code);
  4293. workOrd.CreateGLforLaborVar = curItem == null ? false : curItem.Install;
  4294. workOrd.CreateTime = DateTime.Now;
  4295. workOrd.Typed = "";
  4296. workOrd.IssueSite = "VMI";
  4297. workOrd.Urgent = 0;
  4298. var me = WriteMoentry.Find(s => s.moentry_moid == item.Id);
  4299. var curcrmo = me == null ? null : crmoList.Where(c => me.fbill_no == c.bill_no).ToList();
  4300. var curcust = curcrmo.Any() ? cust.Where(c => curcrmo[0].custom_no == c.Cust).ToList() : null;
  4301. workOrd.CustNo = curcust!=null ? (curcust.Any()?curcust[0].Cust : "") : "";
  4302. workOrd.Class = curcust != null ? (curcust.Any() ? decimal.Parse(curcust[0].Class == "" ? "0" : curcust[0].Class) : 9999) : 9999;
  4303. //workOrd.SalesJob = item.morder_no;
  4304. workOrds.Add(workOrd);
  4305. //添加工单工艺路线数据
  4306. var curRoutings = allRoutings.Where(p => p.RoutingCode == item.product_code).ToList();
  4307. foreach (var dtl in curRoutings)
  4308. {
  4309. woRouting = new WorkOrdRouting();
  4310. woRouting.Domain = item.factory_id.ToString();
  4311. woRouting.Descr = dtl.Descr;
  4312. woRouting.MilestoneOp = dtl.MilestoneOp;
  4313. woRouting.WorkOrd = item.morder_no;
  4314. woRouting.OP = dtl.Op;
  4315. woRouting.ParentOp = dtl.ParentOp;
  4316. woRouting.RunTime = dtl.RunTime;
  4317. woRouting.ItemNum = item.product_code;
  4318. woRouting.QtyOrded = item.need_number.GetValueOrDefault();
  4319. woRouting.OverlapUnits = dtl.OverlapUnits;
  4320. woRouting.Status = "";
  4321. woRouting.IsActive = true;
  4322. woRouting.CommentIndex = dtl.CommentIndex;
  4323. woRouting.CreateTime = DateTime.Now;
  4324. woRouting.StdOp = dtl.StdOp;
  4325. woRouting.PackingQty = dtl.PackingQty.GetValueOrDefault();
  4326. workOrdRoutings.Add(woRouting);
  4327. }
  4328. long fid = GetParentMo(morders, item);
  4329. var exm = exmResult.Find(s => s.morder_id == fid);
  4330. if (exm != null)
  4331. {
  4332. var childs = childExamineList.Where(s => s.examine_id == exm.Id && s.is_use == true).ToList();
  4333. var child = childs.Find(s => s.item_number == item.product_code);
  4334. if (child == null)
  4335. {
  4336. continue;
  4337. }
  4338. List<b_bom_child_examine> returnList = new List<b_bom_child_examine>();
  4339. var productOps = productOpList.Where(x => x.ProductItem == item.product_code).ToList();
  4340. GetWorkDetalis(childs.Where(s => s.parent_id == child.fid).ToList(), returnList, childs, productOps);
  4341. if (returnList.Any())
  4342. {
  4343. WorkOrdDetail woDetail = null;
  4344. var calereturnList = returnList.OrderBy(c => c.item_number).Select(x => x.item_number).Distinct().ToList();
  4345. short num = 1;
  4346. foreach (var caleNumber in calereturnList)
  4347. {
  4348. var caleList = returnList.Where(x => x.item_number == caleNumber).ToList();
  4349. var itemMst = itemMasters.Find(x => x.ItemNum == caleNumber);
  4350. //添加工单的物料信息
  4351. woDetail = new WorkOrdDetail();
  4352. woDetail.Domain = item.factory_id.ToString();
  4353. woDetail.WorkOrd = item.morder_no;
  4354. var oplist = caleList.Where(x => x.Op > 0).ToList();
  4355. woDetail.Op = 0;
  4356. if (oplist.Any())
  4357. {
  4358. woDetail.Op = oplist.Min(f => f.Op);
  4359. }
  4360. woDetail.ItemNum = caleNumber;
  4361. woDetail.QtyPosted = 0m;
  4362. woDetail.QtyReturned = 0m;
  4363. woDetail.Status = "";
  4364. woDetail.IsActive = true;
  4365. woDetail.CreateTime = DateTime.Now;
  4366. woDetail.Line = num;
  4367. woDetail.QtyRequired = caleList.Sum(c => c.needCount.GetValueOrDefault());
  4368. woDetail.Location = itemMst == null ? "" : itemMst.Location;
  4369. if (workOrd.QtyOrded != 0)
  4370. {
  4371. woDetail.FrozenBOMQty = Math.Round(woDetail.QtyRequired / workOrd.QtyOrded, 10);
  4372. }
  4373. workOrdDetails.Add(woDetail);
  4374. num++;
  4375. }
  4376. }
  4377. }
  4378. }
  4379. }
  4380. public long GetParentMo(List<mes_morder> morders, mes_morder item)
  4381. {
  4382. if (item.parent_id != null)
  4383. {
  4384. var parentMo = morders.Find(s => s.Id == item.parent_id);
  4385. if (parentMo != null)
  4386. {
  4387. return GetParentMo(morders, parentMo);
  4388. }
  4389. else
  4390. {
  4391. return item.Id;
  4392. }
  4393. }
  4394. else
  4395. {
  4396. return item.Id;
  4397. }
  4398. }
  4399. /// <summary>
  4400. /// 获取虚拟件明细
  4401. /// </summary>
  4402. /// <param name="dtl"></param>
  4403. /// <param name="returnList"></param>
  4404. /// <param name="childs"></param>
  4405. public void GetWorkDetalis(List<BomChildExamineDto> dtl, List<BomChildExamineDto> returnList, List<BomChildExamineDto> childs, List<ProductStructureOp> productOps)
  4406. {
  4407. returnList.AddRange(dtl.Where(x => x.erp_cls != 4).ToList());
  4408. var rst = childs.Where(s => dtl.Where(x => x.erp_cls == 4).Select(c => c.fid).Contains(s.parent_id.GetValueOrDefault())).ToList();
  4409. if (rst.Any())
  4410. {
  4411. if (productOps.Any())
  4412. {
  4413. //rst 虚拟件的子物料
  4414. foreach (var item in rst)
  4415. {
  4416. var parent = childs.Find(x => x.fid == item.parent_id);
  4417. if (parent != null)
  4418. {
  4419. var proOp = productOps.Find(x => x.ParentItem == parent.item_number && x.ComponentItem == item.item_number);
  4420. if (proOp != null)
  4421. {
  4422. item.Op = proOp.Op;
  4423. }
  4424. }
  4425. }
  4426. }
  4427. GetWorkDetalis(rst, returnList, childs, productOps);
  4428. }
  4429. return;
  4430. }
  4431. /// <summary>
  4432. /// 获取虚拟件明细
  4433. /// </summary>
  4434. /// <param name="dtl"></param>
  4435. /// <param name="returnList"></param>
  4436. /// <param name="childs"></param>
  4437. public void GetWorkDetalis(List<b_bom_child_examine> dtl, List<b_bom_child_examine> returnList, List<b_bom_child_examine> childs, List<ProductStructureOp> productOps)
  4438. {
  4439. returnList.AddRange(dtl.Where(x => x.erp_cls != 4).ToList());
  4440. var rst = childs.Where(s => dtl.Where(x => x.erp_cls == 4).Select(c => c.fid).Contains(s.parent_id.GetValueOrDefault())).ToList();
  4441. if (rst.Any())
  4442. {
  4443. if (productOps.Any())
  4444. {
  4445. //rst 虚拟件的子物料
  4446. foreach (var item in rst)
  4447. {
  4448. var parent = childs.Find(x => x.fid == item.parent_id);
  4449. if (parent != null)
  4450. {
  4451. var proOp = productOps.Find(x => x.ParentItem == parent.item_number && x.ComponentItem == item.item_number);
  4452. if (proOp != null)
  4453. {
  4454. item.Op = proOp.Op;
  4455. }
  4456. }
  4457. }
  4458. }
  4459. GetWorkDetalis(rst, returnList, childs, productOps);
  4460. }
  4461. return;
  4462. }
  4463. /// <summary>
  4464. /// 根据工单编号排优先级
  4465. /// </summary>
  4466. /// <param name="workOrdMasters">工单编号列表</param>
  4467. /// <param name="domain">工厂编码</param>
  4468. /// <returns></returns>
  4469. //计算工单优先级
  4470. //public List<WorkOrdMaster> CalcPriority(List<string> workOrdMasters,string domain)
  4471. //{
  4472. // var works= _workOrdMaster.Select(a => workOrdMasters.Contains(a.WorkOrd) && a.Domain == domain && a.IsActive);
  4473. // var saleWordOrd = works.Where(a => !string.IsNullOrEmpty(a.SalesJob));
  4474. // var soList=_mysql_crm_seorder.GetListAsync(a=> saleWordOrd.Select(b=>b.SalesJob).Contains(a.bill_no)).Result;
  4475. // var custList = _custMaster.Select(a => soList.Select(b => b.custom_no).Contains(a.Cust) && a.Domain == domain);
  4476. // //T1海外客户
  4477. // var T1CustList = custList.FindAll(a => a.Terms == "T1" || a.Terms == "海外").Select(a => a.Cust);
  4478. // //国科海王客户
  4479. // var T2CustList = custList.FindAll(a => a.Terms == "国科" || a.Terms == "海王").Select(a => a.Cust);
  4480. // //T1海外订单
  4481. // var T1SOList = soList.Where(a => T1CustList.Contains(a.custom_no)).Select(a => a.bill_no);
  4482. // //国科海王订单
  4483. // var T2SOList = soList.Where(a => T2CustList.Contains(a.custom_no)).Select(a => a.bill_no);
  4484. // //T1海外工单
  4485. // var T1WOList = saleWordOrd.Where(a => T1SOList.Contains(a.SalesJob)).ToList();
  4486. // //国科海王工单
  4487. // var T2WOList = saleWordOrd.Where(a => T2SOList.Contains(a.SalesJob)).ToList();
  4488. // //在制工单
  4489. // var inProductList = _mes_mooccupy.GetListAsync(a => works.Select(a => a.WorkOrd).Contains(a.moo_mo)).Result;
  4490. // //优先1:T1、海外销售订单新产生的生产指令;
  4491. // var T1WOListNew=T1WOList.Where(a=> !inProductList.Select(b=>b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ThenBy(a => a.OrdDate).ToList();
  4492. // //优先2:T1、海外销售订单关联的在制生产指令;
  4493. // var T1WOListInProduct = T1WOList.Where(a => inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ThenBy(a => a.OrdDate).ToList();
  4494. // //优先3:平台(国科、海王)销售订单新产生的生产指令;
  4495. // var T2WOListNew = T2WOList.Where(a => !inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ThenBy(a => a.OrdDate).ToList();
  4496. // //优先4:平台(国科、海王)销售订单关联的在制生产指令;
  4497. // var T2WOListInProduct = T2WOList.Where(a => !inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ThenBy(a => a.OrdDate).ToList();
  4498. // //优先5:除销售订单以外,计划补货订单关联的生产指令;
  4499. // var PlanWOList = works.Except(T1WOListNew).ToList();
  4500. // PlanWOList = works.Except(T1WOListInProduct).ToList();
  4501. // PlanWOList = works.Except(T2WOListNew).ToList();
  4502. // PlanWOList = works.Except(T2WOListInProduct).ToList();
  4503. // PlanWOList= PlanWOList.OrderBy(a => a.DueDate).ThenBy(a => a.OrdDate).ToList();
  4504. // //先按生产指令的类型,再按生产指令的完工日期顺序排产;
  4505. // List<WorkOrdMaster> orderedList = new List<WorkOrdMaster>();
  4506. // decimal Priority = 1.0m;
  4507. // for (int i=0;i< T1WOListNew.Count;i++)
  4508. // {
  4509. // T1WOListNew[i].Priority = Priority;
  4510. // orderedList.Add(T1WOListNew[i]);
  4511. // Priority = Priority + 1.0m;
  4512. // }
  4513. // for (int i = 0; i < T1WOListInProduct.Count; i++)
  4514. // {
  4515. // T1WOListInProduct[i].Priority = Priority;
  4516. // orderedList.Add(T1WOListInProduct[i]);
  4517. // Priority = Priority + 1.0m;
  4518. // }
  4519. // for (int i = 0; i < T2WOListNew.Count; i++)
  4520. // {
  4521. // T2WOListNew[i].Priority = Priority;
  4522. // orderedList.Add(T2WOListNew[i]);
  4523. // Priority = Priority + 1.0m;
  4524. // }
  4525. // for (int i = 0; i < T2WOListInProduct.Count; i++)
  4526. // {
  4527. // T2WOListInProduct[i].Priority = Priority;
  4528. // orderedList.Add(T2WOListInProduct[i]);
  4529. // Priority = Priority + 1.0m;
  4530. // }
  4531. // for (int i = 0; i < PlanWOList.Count; i++)
  4532. // {
  4533. // PlanWOList[i].Priority = Priority;
  4534. // orderedList.Add(PlanWOList[i]);
  4535. // Priority = Priority + 1.0m;
  4536. // }
  4537. // return orderedList;
  4538. //}
  4539. public List<WorkOrdMaster> CalcPriority(List<string> workOrdMasters, string domain)
  4540. {
  4541. var works = _workOrdMaster.Select(a => workOrdMasters.Contains(a.WorkOrd) && a.Domain == domain && a.IsActive);
  4542. works = works.OrderBy(a => a.DueDate).ThenBy(a => a.OrdDate).ToList();
  4543. List<WorkOrdMaster> orderedList = new List<WorkOrdMaster>();
  4544. decimal Priority = 1.0m;
  4545. for (int i = 0; i < works.Count; i++)
  4546. {
  4547. works[i].Priority = Priority;
  4548. orderedList.Add(works[i]);
  4549. Priority = Priority + 1.0m;
  4550. }
  4551. return orderedList;
  4552. }
  4553. public static object GetPropertyValue(object obj, string propName)
  4554. {
  4555. return obj.GetType().GetProperty(propName).GetValue(obj, null);
  4556. }
  4557. public List<WorkOrdMaster> RefreshPriority(List<string> workOrdMasters, string domain)
  4558. {
  4559. if (workOrdMasters == null)
  4560. {
  4561. var workOrds = _workOrdMaster.Select(a => (string.IsNullOrEmpty(a.Status) || a.Status.ToUpper() == "P") && a.Typed.ToUpper() != "PW" && a.Domain == domain && a.IsActive);
  4562. workOrdMasters = workOrds.Select(w => w.WorkOrd).ToList();
  4563. }
  4564. //优先级越高越往后排
  4565. var prioritylist = _PriorityCode.Select(p => p.IsActive && p.Domain == domain).OrderBy(p => p.Priority).ToList();
  4566. //排序字段
  4567. string[] sortColumns = new string[prioritylist.Count];
  4568. bool[] sortDirections = new bool[prioritylist.Count];
  4569. for (int i = 0; i < prioritylist.Count; i++)
  4570. {
  4571. sortColumns[i] = prioritylist[i].Value;
  4572. sortDirections[i] = prioritylist[i].OrderBy;
  4573. if (prioritylist[i].SourceTable != "WorkOrdMaster")
  4574. {
  4575. //更新数据到工单表中
  4576. var sql = $"update WorkOrdMaster set {prioritylist[i].Value}=b.{prioritylist[i].SourceColumn} from WorkOrdMaster a,{prioritylist[i].SourceTable} b where a.{prioritylist[i].ValueID}=b.{prioritylist[i].SourceID}";
  4577. if (prioritylist[i].SourceType != prioritylist[i].ValueType)
  4578. {
  4579. sql = $"update WorkOrdMaster set {prioritylist[i].Value}=cast(iif(cast(b.{prioritylist[i].SourceColumn} as VARCHAR)='','0',cast(b.{prioritylist[i].SourceColumn} as VARCHAR)) as {prioritylist[i].ValueType}) from WorkOrdMaster a,{prioritylist[i].SourceTable} b where a.{prioritylist[i].ValueID}=b.{prioritylist[i].SourceID}";
  4580. }
  4581. _businessDbContext.Database.ExecuteSqlRaw(sql);
  4582. }
  4583. }
  4584. var works = _workOrdMaster.Select(a => workOrdMasters.Contains(a.WorkOrd) && a.Domain == domain && a.IsActive);
  4585. var occupy = _mysql_mes_mooccupy.GetListAsync(m=> works.Select(w=>w.WorkOrd).Contains(m.moo_mo)).Result;
  4586. var crmoList = _mysql_crm_seorder.GetListAsync(m => occupy.Select(s => s.fbill_no).ToList().Contains(m.bill_no) && !m.IsDeleted).Result;
  4587. var cust = _custMaster.Select(c => c.IsActive && c.Domain == domain && crmoList.Select(m => m.custom_no).Contains(c.Cust)).ToList();
  4588. for (int i = 0; i < works.Count; i++)
  4589. {
  4590. var curoccupy = occupy.Where(o => o.moo_mo == works[i].WorkOrd).ToList();
  4591. //计划工单被占用后客户优先级更新
  4592. if (curoccupy.Any())
  4593. {
  4594. var curcrmo = crmoList.Where(c => curoccupy.Select(o => o.fbill_no).ToList().Contains(c.bill_no)).ToList();
  4595. var curcust = cust.Where(c => curcrmo.Select(m => m.custom_no).Contains(c.Cust)).ToList();
  4596. if (curcust.Any())
  4597. {
  4598. works[i].Class = decimal.Parse(curcust.Max(c => c.Class));
  4599. }
  4600. else
  4601. {
  4602. works[i].Class = 0m;
  4603. }
  4604. }
  4605. else
  4606. {
  4607. works[i].Class = 9999m;
  4608. }
  4609. }
  4610. works.Sort(new DynamicOrderComparer<WorkOrdMaster>(sortColumns, sortDirections));
  4611. decimal Priority = 1.0m;
  4612. for (int i = 0; i < works.Count; i++)
  4613. {
  4614. works[i].Priority = Priority;
  4615. Priority = Priority + 1.0m;
  4616. //拼接
  4617. var str = "";
  4618. foreach (var fieldName in sortColumns)
  4619. {
  4620. PropertyInfo propertyInfo = works[i].GetType().GetProperty(fieldName);
  4621. if (propertyInfo != null)
  4622. {
  4623. str += "." + (propertyInfo.GetValue(works[i]) == null ? "0" : propertyInfo.GetValue(works[i]).ToString());
  4624. }
  4625. }
  4626. works[i].PriorityNo = str.Substring(1);
  4627. }
  4628. _businessDbContext.UpdateRange(works);
  4629. return works;
  4630. }
  4631. /// <summary>
  4632. /// 根据工单排优先级(用于先排优先级再写入的场景)
  4633. /// </summary>
  4634. /// <param name="workOrdMasters">工单编号列表</param>
  4635. /// <param name="domain">工厂编码</param>
  4636. /// <returns></returns>
  4637. //计算工单优先级
  4638. //public List<WorkOrdMaster> CalcPriority(List<WorkOrdMaster> works, string domain)
  4639. //{
  4640. // var saleWordOrd = works.Where(a => !string.IsNullOrEmpty(a.SalesJob));
  4641. // var soList = _mysql_crm_seorder.GetListAsync(a => saleWordOrd.Select(b => b.SalesJob).Contains(a.bill_no)).Result;
  4642. // var custList = _custMaster.Select(a => soList.Select(b => b.custom_no).Contains(a.Cust) && a.Domain == domain);
  4643. // //T1海外客户
  4644. // var T1CustList = custList.FindAll(a => a.Terms == "T1" || a.Terms == "海外").Select(a => a.Cust);
  4645. // //国科海王客户
  4646. // var T2CustList = custList.FindAll(a => a.Terms == "国科" || a.Terms == "海王").Select(a => a.Cust);
  4647. // //T1海外订单
  4648. // var T1SOList = soList.Where(a => T1CustList.Contains(a.custom_no)).Select(a => a.bill_no);
  4649. // //国科海王订单
  4650. // var T2SOList = soList.Where(a => T2CustList.Contains(a.custom_no)).Select(a => a.bill_no);
  4651. // //T1海外工单
  4652. // var T1WOList = saleWordOrd.Where(a => T1SOList.Contains(a.SalesJob)).ToList();
  4653. // //国科海王工单
  4654. // var T2WOList = saleWordOrd.Where(a => T2SOList.Contains(a.SalesJob)).ToList();
  4655. // //在制工单
  4656. // var inProductList = _mes_mooccupy.GetListAsync(a => works.Select(a => a.WorkOrd).Contains(a.moo_mo)).Result;
  4657. // //优先1:T1、海外销售订单新产生的生产指令;
  4658. // var T1WOListNew = T1WOList.Where(a => !inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ThenBy(a=>a.OrdDate).ToList();
  4659. // //优先2:T1、海外销售订单关联的在制生产指令;
  4660. // var T1WOListInProduct = T1WOList.Where(a => inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ThenBy(a=>a.OrdDate).ToList();
  4661. // //优先3:平台(国科、海王)销售订单新产生的生产指令;
  4662. // var T2WOListNew = T2WOList.Where(a => !inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ThenBy(a=>a.OrdDate).ToList();
  4663. // //优先4:平台(国科、海王)销售订单关联的在制生产指令;
  4664. // var T2WOListInProduct = T2WOList.Where(a => !inProductList.Select(b => b.moo_mo).Contains(a.WorkOrd))?.OrderBy(a => a.DueDate).ThenBy(a=>a.OrdDate).ToList();
  4665. // //优先5:除销售订单以外,计划补货订单关联的生产指令;
  4666. // var PlanWOList = works.Except(T1WOListNew).ToList();
  4667. // PlanWOList = works.Except(T1WOListInProduct).ToList();
  4668. // PlanWOList = works.Except(T2WOListNew).ToList();
  4669. // PlanWOList = works.Except(T2WOListInProduct).ToList();
  4670. // PlanWOList = PlanWOList.OrderBy(a => a.DueDate).ThenBy(a=>a.OrdDate).ToList();
  4671. // //先按生产指令的类型,再按生产指令的完工日期顺序排产;
  4672. // List<WorkOrdMaster> orderedList = new List<WorkOrdMaster>();
  4673. // decimal Priority = 1.0m;
  4674. // for (int i = 0; i < T1WOListNew.Count; i++)
  4675. // {
  4676. // T1WOListNew[i].Priority = Priority;
  4677. // orderedList.Add(T1WOListNew[i]);
  4678. // Priority = Priority + 1.0m;
  4679. // }
  4680. // for (int i = 0; i < T1WOListInProduct.Count; i++)
  4681. // {
  4682. // T1WOListInProduct[i].Priority = Priority;
  4683. // orderedList.Add(T1WOListInProduct[i]);
  4684. // Priority = Priority + 1.0m;
  4685. // }
  4686. // for (int i = 0; i < T2WOListNew.Count; i++)
  4687. // {
  4688. // T2WOListNew[i].Priority = Priority;
  4689. // orderedList.Add(T2WOListNew[i]);
  4690. // Priority = Priority + 1.0m;
  4691. // }
  4692. // for (int i = 0; i < T2WOListInProduct.Count; i++)
  4693. // {
  4694. // T2WOListInProduct[i].Priority = Priority;
  4695. // orderedList.Add(T2WOListInProduct[i]);
  4696. // Priority = Priority + 1.0m;
  4697. // }
  4698. // for (int i = 0; i < PlanWOList.Count; i++)
  4699. // {
  4700. // PlanWOList[i].Priority = Priority;
  4701. // orderedList.Add(PlanWOList[i]);
  4702. // Priority = Priority + 1.0m;
  4703. // }
  4704. // return orderedList;
  4705. //}
  4706. public List<WorkOrdMaster> CalcPriority(List<WorkOrdMaster> works, string domain)
  4707. {
  4708. works = works.OrderBy(a => a.DueDate).ThenBy(a => a.OrdDate).ToList();
  4709. //先按生产指令的类型,再按生产指令的完工日期顺序排产;
  4710. List<WorkOrdMaster> orderedList = new List<WorkOrdMaster>();
  4711. decimal Priority = 1.0m;
  4712. for (int i = 0; i < works.Count; i++)
  4713. {
  4714. works[i].Priority = Priority;
  4715. orderedList.Add(works[i]);
  4716. Priority = Priority + 1.0m;
  4717. }
  4718. return orderedList;
  4719. }
  4720. //所有未下达的工单按照日期排序计算优先级
  4721. public void CalcPriority(string domain)
  4722. {
  4723. var works = _workOrdMaster.Select(a => (string.IsNullOrEmpty(a.Status) || a.Status.ToUpper() == "P") && a.Typed.ToUpper() != "PW" && a.Domain == domain && a.IsActive);
  4724. works = works.OrderBy(a => a.OrdDate).ToList();
  4725. var workOrdsList = works.Select(a => a.WorkOrd).ToList();
  4726. var weekPlan = _replenishmentWeekPlan.GetListAsync(a => a.IsReplenishmentModel == "N" && workOrdsList.Contains(a.ProductionOrder)).Result;
  4727. decimal Priority = 1.0m;
  4728. for (int i = 0; i < works.Count; i++)
  4729. {
  4730. works[i].Priority = Priority;
  4731. if (weekPlan.Any(a => a.ProductionOrder == works[i].WorkOrd))
  4732. {
  4733. weekPlan.First(a => a.ProductionOrder == works[i].WorkOrd).Priority = Priority;
  4734. }
  4735. Priority = Priority + 1.0m;
  4736. }
  4737. _businessDbContext.UpdateRange(works);
  4738. _businessDbContext.UpdateRange(weekPlan);
  4739. }
  4740. /// <summary>
  4741. /// 手动调整优先级
  4742. /// </summary>
  4743. /// <param name="workOrdMasters">工单编号列表</param>
  4744. /// <param name="domain">工厂编码</param>
  4745. /// <returns></returns>
  4746. //计算工单优先级
  4747. public async Task<string> ChangePriority(string weekplanid, string tenant_id, string factory_id, string company_id, string itemNumber, string qty, string instockdate, string priority)
  4748. {
  4749. try
  4750. {
  4751. if (string.IsNullOrEmpty(qty))
  4752. return "数量不正确,请检查";
  4753. if (string.IsNullOrEmpty(instockdate))
  4754. return "成品入库日期不正确,请检查";
  4755. if (string.IsNullOrEmpty(priority))
  4756. return "优先级不正确,请检查";
  4757. decimal newpriority = Convert.ToDecimal(priority);
  4758. DateTime newinstockdate = Convert.ToDateTime(instockdate);
  4759. decimal newqty = Convert.ToDecimal(qty);
  4760. long id = Convert.ToInt64(weekplanid);
  4761. long tenantid = Convert.ToInt64(tenant_id);
  4762. long factoryid = Convert.ToInt64(factory_id);
  4763. long companyid = Convert.ToInt64(company_id);
  4764. var weekPlan = _replenishmentWeekPlan.FindAsync(a => a.Id == id && a.tenant_id == tenantid && a.factory_id == factoryid && a.company_id == companyid).Result;
  4765. //周计划没有生成周工单的不校验优先级重复
  4766. if (weekPlan != null && !string.IsNullOrEmpty(weekPlan.ProductionOrder))
  4767. {
  4768. var isExistSamePriority = _workOrdMaster.Select(a => a.WorkOrd != weekPlan.ProductionOrder && (string.IsNullOrEmpty(a.Status) || a.Status.ToUpper() == "P") && (string.IsNullOrEmpty(a.Typed) || (!string.IsNullOrEmpty(a.Typed) && a.Typed.ToUpper() != "PW" && a.BusinessID > 0)) && a.Priority == newpriority);
  4769. if (isExistSamePriority.Any())
  4770. return "优先级重复,请重新调整。";
  4771. }
  4772. weekPlan.Priority = newpriority;
  4773. weekPlan.Qty = newqty;
  4774. //newinstockdate其实传的的工单开工日期
  4775. weekPlan.PlanStartDate = newinstockdate;
  4776. if (!string.IsNullOrEmpty(weekPlan.ProductionOrder))
  4777. {
  4778. long bang_id = help.NextId();
  4779. var moList = _mysql_mes_morder.GetListAsync(a => a.morder_no == weekPlan.ProductionOrder && a.factory_id == factoryid).Result;
  4780. var moentryList = _mysql_mes_moentry.GetListAsync(a => a.moentry_mono == weekPlan.ProductionOrder && a.factory_id == factoryid).Result;
  4781. var workmasterList = _workOrdMaster.Select(a => a.WorkOrd == weekPlan.ProductionOrder && a.Domain == factory_id);
  4782. var workRoutings = _workOrdRouting.Select(a => a.WorkOrd == weekPlan.ProductionOrder && a.Domain == factory_id);
  4783. //判断
  4784. if (moList.Count > 0 && (moList[0].morder_state == MorderEnum.Initial_state || string.IsNullOrEmpty(moList[0].morder_state))
  4785. && workmasterList.Count > 0 && (string.IsNullOrEmpty(workmasterList[0].Status) || workmasterList[0].Status == "p"))
  4786. {
  4787. moList[0].moentry_sys_stime = newinstockdate;
  4788. moList[0].need_number = newqty;
  4789. moList[0].morder_production_number = newqty;
  4790. moentryList[0].need_number = newqty;
  4791. moentryList[0].morder_production_number = newqty;
  4792. workmasterList[0].OrdDate = newinstockdate;
  4793. workmasterList[0].Priority = newpriority;
  4794. workmasterList[0].QtyOrded = newqty;
  4795. workRoutings?.ForEach(a =>
  4796. {
  4797. a.QtyOrded = newqty;
  4798. });
  4799. await PlanOrderResourceCheck(moList.OrderBy(a => a.moentry_sys_stime).ToList(), moentryList, bang_id, "", true, false);
  4800. var examine_resultList = _mysql_examine_result.GetListAsync(a => a.bangid == bang_id).Result;
  4801. if (weekPlan.IsReplenishmentModel == "N")
  4802. {
  4803. var moItem = examine_resultList.Find(b => b.morder_no == weekPlan.ProductionOrder);
  4804. List<RoutingOpDetail> routingOp = routingOps.Where(x => x.RoutingCode == weekPlan.ItemNumber).ToList();
  4805. //组装标准工时
  4806. var Assembly = routingOp.Where(x => x.Ufld1 == "组装" && x.MilestoneOp).FirstOrDefault();
  4807. //热封标准工时
  4808. var HeatSealing = routingOp.Where(x => x.Ufld1 == "热封" && x.MilestoneOp).FirstOrDefault();
  4809. //包装标准工时
  4810. var Packaging = routingOp.Where(x => x.Descr == "包装" && x.MilestoneOp).FirstOrDefault();
  4811. if (moItem != null && moItem.kitting_times < weekPlan.PlanStartDate)
  4812. {
  4813. weekPlan.ItemStatus = "齐套";
  4814. weekPlan.PlanKittingDate = moItem.kitting_times;
  4815. weekPlan.AssembleHours = Assembly == null ? 0 : Assembly.RunTime * weekPlan.Qty;
  4816. weekPlan.HeatSealHours = HeatSealing == null ? 0 : HeatSealing.RunTime * weekPlan.Qty;
  4817. weekPlan.PackageHours = Packaging == null ? 0 : Packaging.RunTime * weekPlan.Qty;
  4818. weekPlan.TotalHours = weekPlan.AssembleHours + weekPlan.HeatSealHours + weekPlan.PackageHours;
  4819. }
  4820. else
  4821. {
  4822. weekPlan.ItemStatus = "欠料";
  4823. weekPlan.PlanKittingDate = moItem.kitting_times;
  4824. weekPlan.AssembleHours = Assembly == null ? 0 : Assembly.RunTime * weekPlan.Qty;
  4825. weekPlan.HeatSealHours = HeatSealing == null ? 0 : HeatSealing.RunTime * weekPlan.Qty;
  4826. weekPlan.PackageHours = Packaging == null ? 0 : Packaging.RunTime * weekPlan.Qty;
  4827. weekPlan.TotalHours = weekPlan.AssembleHours + weekPlan.HeatSealHours + weekPlan.PackageHours;
  4828. }
  4829. }
  4830. string sql = "UPDATE mes_morder SET moentry_sys_stime='" + newinstockdate + "',need_number=" + newqty + ",morder_production_number=" + newqty + " WHERE morder_no='" + weekPlan.ProductionOrder + "';" +
  4831. "UPDATE mes_moentry SET need_number=" + newqty + ",morder_production_number=" + newqty + " WHERE moentry_mono='" + weekPlan.ProductionOrder + "';" +
  4832. "UPDATE WorkOrdMaster SET OrdDate='" + newinstockdate + "',Priority=" + newpriority + ",QtyOrded=" + newqty + " WHERE WorkOrd='" + weekPlan.ProductionOrder + "';" +
  4833. "UPDATE WorkOrdRouting SET QtyOrded=" + newqty + " WHERE WorkOrd='" + weekPlan.ProductionOrder + "'; " +
  4834. "UPDATE WorkOrdDetail SET QtyRequired=CEILING(" + newqty + "*FrozenBOMQty) WHERE WorkOrd='" + weekPlan.ProductionOrder + "'; ";
  4835. _businessDbContext.Database.ExecuteSqlRaw(sql);
  4836. await _replenishmentWeekPlan.UpdateAsync(weekPlan);
  4837. /*await _mysql_mes_morder.UpdateManyAsync(moList);
  4838. await _mysql_mes_moentry.UpdateManyAsync(moentryList);
  4839. _workOrdMaster.Update(workmasterList);
  4840. _workOrdRouting.Update(workRoutings);*/
  4841. }
  4842. else
  4843. {
  4844. return "工单不是初始状态,不允许调整。";
  4845. }
  4846. }
  4847. else
  4848. {
  4849. await _replenishmentWeekPlan.UpdateAsync(weekPlan);
  4850. return "ok";
  4851. }
  4852. }
  4853. catch (Exception e)
  4854. {
  4855. return "调整失败,请联系管理员。";
  4856. }
  4857. return "ok";
  4858. }
  4859. /// <summary>
  4860. /// 手动调整优先级
  4861. /// </summary>
  4862. /// <param name="workOrdMasters">工单编号列表</param>
  4863. /// <param name="domain">工厂编码</param>
  4864. /// <returns></returns>
  4865. //计算工单优先级
  4866. public async Task<string> WorkOrdCheckChangePriority(string WorkOrd, string tenant_id, string factory_id, string company_id, string itemNumber, string qty, string LotSerial, string priority,string UserNO)
  4867. {
  4868. try
  4869. {
  4870. if (string.IsNullOrEmpty(qty))
  4871. return "数量不正确,请检查";
  4872. if (string.IsNullOrEmpty(LotSerial))
  4873. return "批号输入不正确,请检查";
  4874. if (string.IsNullOrEmpty(priority))
  4875. return "优先级不正确,请检查";
  4876. decimal newpriority = Convert.ToDecimal(priority);
  4877. decimal newqty = Convert.ToDecimal(qty);
  4878. long tenantid = Convert.ToInt64(tenant_id);
  4879. long factoryid = Convert.ToInt64(factory_id);
  4880. long companyid = Convert.ToInt64(company_id);
  4881. long bang_id = help.NextId();
  4882. var moList = _mysql_mes_morder.GetListAsync(a => a.morder_no == WorkOrd && a.factory_id == factoryid).Result;
  4883. var moentryList = _mysql_mes_moentry.GetListAsync(a => a.moentry_mono == WorkOrd && a.factory_id == factoryid).Result;
  4884. //var workmasterList = _workOrdMaster.Select(a => a.WorkOrd == WorkOrd && a.Domain == factory_id);
  4885. //var workRoutings = _workOrdRouting.Select(a => a.WorkOrd == WorkOrd && a.Domain == factory_id);
  4886. //var workOrddetails = _workOrdDetail.Select(a => a.WorkOrd == WorkOrd && a.Domain == factory_id);
  4887. //var weekPlan = _replenishmentWeekPlan.GetListAsync(a => a.ProductionOrder == WorkOrd && a.tenant_id == tenantid && a.factory_id == factoryid && a.company_id == companyid).Result;
  4888. //判断
  4889. if (moList.Count > 0)// && workmasterList.Count > 0)
  4890. {
  4891. var oldqty = moList[0].need_number;
  4892. moList[0].need_number = newqty;
  4893. moList[0].morder_production_number = newqty;
  4894. moentryList[0].need_number = newqty;
  4895. moentryList[0].morder_production_number = newqty;
  4896. //workmasterList[0].LotSerial = LotSerial;
  4897. //workmasterList[0].Priority = newpriority;
  4898. //workmasterList[0].QtyOrded = newqty;
  4899. //workRoutings?.ForEach(a =>
  4900. //{
  4901. // a.QtyOrded = newqty;
  4902. //});
  4903. //workOrddetails?.ForEach(a =>
  4904. //{
  4905. // a.QtyRequired = Math.Ceiling(newqty * a.FrozenBOMQty);
  4906. //});
  4907. //weekPlan?.ForEach(a =>
  4908. //{
  4909. // a.Priority = newpriority;
  4910. // a.Qty = newqty;
  4911. // a.ProductionBatch = LotSerial;
  4912. //});
  4913. if (oldqty != newqty)
  4914. {
  4915. await PlanOrderResourceCheck(moList.OrderBy(a => a.moentry_sys_stime).ToList(), moentryList, bang_id, "", true, false, false);
  4916. }
  4917. string sql = $"exec [pr_MES_UpdateWorkOrder] @Domian='{factoryid}',@LotSerial='{LotSerial}',@Priority={newpriority},@Qty={newqty},@WorkOrd='{WorkOrd}',@UserNO='{UserNO}'";
  4918. _businessDbContext.Database.ExecuteSqlRaw(sql);
  4919. //using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
  4920. //{
  4921. // try
  4922. // {
  4923. //_businessDbContext.UpdateRange(moList);
  4924. //_businessDbContext.UpdateRange(moentryList);
  4925. //_businessDbContext.UpdateRange(workmasterList);
  4926. //if (weekPlan.Any())
  4927. //{
  4928. // _businessDbContext.UpdateRange(weekPlan);
  4929. //}
  4930. //if (workRoutings.Any())
  4931. //{
  4932. // _businessDbContext.UpdateRange(workRoutings);
  4933. //}
  4934. //if (workOrddetails.Any())
  4935. //{
  4936. // _businessDbContext.UpdateRange(workOrddetails);
  4937. // if (oldqty != newqty)
  4938. // {
  4939. // var nbrList = _nbrMaster.Select(x => x.Domain == param.factoryId.ToString() && x.WorkOrd == WorkOrd && x.Type == "SM").ToList();
  4940. // if (nbrList.Any())
  4941. // {
  4942. // nbrList.ForEach(x =>
  4943. // {
  4944. // x.Status = "";
  4945. // });
  4946. // var nbrDtlList = _nbrDetail.Select(x => nbrList.Select(c => c.RecID).Contains(x.NbrRecID) && x.IsActive).ToList();
  4947. // if (nbrDtlList.Any())
  4948. // {
  4949. // nbrDtlList.ForEach(x =>
  4950. // {
  4951. // var itemnum = workOrddetails.Find(w => w.ItemNum == x.ItemNum);
  4952. // //仅修改大于已发数的领料明细
  4953. // x.Status = itemnum == null ? x.Status : (itemnum.QtyRequired > x.QtyRec ? "" : x.Status);
  4954. // x.QtyOrd = itemnum == null ? x.QtyOrd : (itemnum.QtyRequired > x.QtyRec ? itemnum.QtyRequired : x.QtyOrd);
  4955. // x.CurrQtyOpened = itemnum == null ? x.QtyOrd : (itemnum.QtyRequired > x.QtyRec ? itemnum.QtyRequired : x.QtyOrd);
  4956. // });
  4957. // _businessDbContext.UpdateRange(nbrDtlList);
  4958. // }
  4959. // _businessDbContext.UpdateRange(nbrList);
  4960. // }
  4961. // }
  4962. //}
  4963. // await unitOfWork.CompleteAsync();
  4964. //}
  4965. //catch (Exception e)
  4966. //{
  4967. // unitOfWork.Dispose();
  4968. // new NLogHelper("ReplenishmentAppService").WriteLog("WorkOrdCheckChangePriority", "工单数据更新失败:" + e.Message, _currentTenant.Id.ToString());
  4969. //}
  4970. //}
  4971. }
  4972. else
  4973. {
  4974. return "未找到对应工单,不允许调整。";
  4975. }
  4976. }
  4977. catch (Exception e)
  4978. {
  4979. return "调整失败,请联系管理员。";
  4980. }
  4981. return "ok";
  4982. }
  4983. /// <summary>
  4984. /// 根据物料编码获取可用库存
  4985. /// 成品半成品可用库存为没有被其他SO和PO占用的(合格成品或半成品库存+WIP)
  4986. /// 原材料可用库存为没有被其他SO和PO占用的(合格原材料库存+在途库存);
  4987. /// </summary>
  4988. /// <param name="itemNumbers">物料编码列表</param>
  4989. /// <returns></returns>
  4990. public List<EOPDto> CalcStock(List<string> itemNumbers, InputDto input)
  4991. {
  4992. List<EOPDto> itemQty = new List<EOPDto>();
  4993. var locations = _invMaster.Select(p => p.Domain == input.factory_id.ToString() && itemNumbers.Contains(p.ItemNum) && p.IsActive);
  4994. //var sapInvList = _SAPInv.Select(a => a.WERKS == input.factory_id.ToString() && itemNumbers.Contains(a.MATNR) && (a.SOBKZ.ToUpper() == "O"));
  4995. var stockOccupyList = _mysql_ic_item_stockoccupy.GetListAsync(a => itemNumbers.Contains(a.icitem_number) && a.factory_id == input.factory_id && !a.IsDeleted).Result;
  4996. itemNumbers.ForEach(a =>
  4997. {
  4998. EOPDto eOPDto = new EOPDto();
  4999. eOPDto.ItemNumber = a;
  5000. decimal stockqty = 0;
  5001. if (locations.Any(s => s.ItemNum == a))
  5002. {
  5003. stockqty = locations.Where(s => s.ItemNum == a).Sum(x => x.AvailStatusQty.GetValueOrDefault());
  5004. }
  5005. decimal InSterilizationQty = 0;
  5006. //if (sapInvList.Count > 0 && sapInvList.Any(s => s.MATNR == a))
  5007. //{
  5008. // InSterilizationQty = sapInvList.Where(s => s.MATNR == a && s.SOBKZ.ToUpper() == "O").Sum(x => Convert.ToDecimal(x.LABST) + Convert.ToDecimal(x.INSME) + Convert.ToDecimal(x.SPEME));
  5009. //}
  5010. stockqty += InSterilizationQty;
  5011. var occupyQty = stockOccupyList.Where(s => s.icitem_number == a).Sum(s => s.quantity);
  5012. stockqty -= occupyQty;
  5013. eOPDto.Qty = stockqty;
  5014. itemQty.Add(eOPDto);
  5015. });
  5016. return itemQty;
  5017. }
  5018. /// <summary>
  5019. /// 计划工单齐套检查
  5020. /// </summary>
  5021. /// <param name="input"></param>
  5022. /// <returns></returns>
  5023. public async Task<string> PlanOrderResourceCheck(List<mes_morder> Mes_Morders, List<mes_moentry> moentryList, long bangid, string analogCalcVersion, bool isChangePriority, bool IsWeekPlan, bool planCheck = true)
  5024. {
  5025. if (Mes_Morders.Any())
  5026. {
  5027. //Mes_Morders.ForEach(s => { s.moentry_sys_stime = DateTime.Now.Date.AddDays((double)lookDay + 1); });
  5028. List<string> monolist = Mes_Morders.Select(c => c.morder_no).ToList();
  5029. if (string.IsNullOrEmpty(analogCalcVersion))
  5030. {
  5031. var workOrds = _workOrdMaster.Select(a => monolist.Contains(a.WorkOrd) && a.Domain == param.factoryId.ToString() && a.IsActive).OrderBy(c => c.Priority).ToList();
  5032. List<mes_morder> PriorityList = new List<mes_morder>();
  5033. foreach (var item in workOrds)
  5034. {
  5035. var mesItem = Mes_Morders.Find(a => a.morder_no == item.WorkOrd);
  5036. if (mesItem != null)
  5037. {
  5038. PriorityList.Add(mesItem);
  5039. }
  5040. }
  5041. if (PriorityList.Any())
  5042. {
  5043. Mes_Morders = PriorityList;
  5044. }
  5045. }
  5046. //清理PR的占用。
  5047. //如果PR没有转PO,则PR没有合并,就删除,有合并,就减少合并后的PR的数量。
  5048. //var prlist = _mysql_srm_pr_main.GetListAsync(s => monolist.Contains(s.pr_mono)).Result;
  5049. //List<srm_pr_main> alllist = new List<srm_pr_main>();
  5050. //List<srm_pr_main> updatelist = new List<srm_pr_main>();
  5051. //List<srm_pr_main> dellist = new List<srm_pr_main>();
  5052. //RecursionGetDbPr2(prlist, alllist);
  5053. //foreach (var pr in prlist)
  5054. //{
  5055. // //找到没有关闭的PR,如果关联上的PR都是已关闭,则说明已经转了PO。
  5056. // //TODO:解决Database operation expected to affect 1 row(s) but actually affected 0 row(s). 如果业务逻辑有问题自行修改
  5057. // var getPr = RerunPr(pr, alllist);
  5058. // if (getPr != null)
  5059. // {
  5060. // if (getPr.pr_aqty - pr.pr_aqty <= 0)
  5061. // {
  5062. // //删除这个pr,没有小于0则是更新
  5063. // dellist.Add(getPr);
  5064. // }
  5065. // else
  5066. // {
  5067. // getPr.pr_aqty = getPr.pr_aqty - pr.pr_aqty;
  5068. // updatelist.Add(getPr);
  5069. // }
  5070. // }
  5071. //}
  5072. List<srm_po_occupy> occupy = await _mysql_srm_po_occupy.GetListAsync(s => monolist.Contains(s.morder_mo));
  5073. _businessDbContext.BulkDelete(occupy);
  5074. //if (updatelist.Any())
  5075. //{
  5076. // _businessDbContext.UpdateRange(updatelist);
  5077. //}
  5078. //if (dellist.Any())
  5079. //{
  5080. // _businessDbContext.BulkDelete(dellist);
  5081. //}
  5082. //清理工单占用
  5083. List<mes_mooccupy> mooccupy = await _mysql_mes_mooccupy.GetListAsync(s => Mes_Morders.Select(c => c.Id).Contains(s.moo_id.GetValueOrDefault()));
  5084. if (mooccupy.Any())
  5085. {
  5086. _businessDbContext.BulkDelete(mooccupy);
  5087. }
  5088. //清理掉库存占用
  5089. var itemstockoccupy = _mysql_ic_item_stockoccupy.GetListAsync(s => monolist.Contains(s.morder_mo)).Result;
  5090. if (itemstockoccupy.Any())
  5091. {
  5092. _businessDbContext.BulkDelete(itemstockoccupy);
  5093. }
  5094. //清理锁定期外的排程数据.
  5095. //var periodList = _periodSequenceDet.Select(s => monolist.Contains(s.WorkOrds));
  5096. //if (periodList.Any())
  5097. //{
  5098. // _periodSequenceDet.Delete(s => monolist.Contains(s.WorkOrds));
  5099. //}
  5100. //var schedulList = _scheduleResultOpMaster.Select(s => monolist.Contains(s.WorkOrd));
  5101. //if (schedulList.Any())
  5102. //{
  5103. // _scheduleResultOpMaster.Delete(s => monolist.Contains(s.WorkOrd));
  5104. //}
  5105. //只走计划工单
  5106. var rtn = await OrderKittingCheck(Mes_Morders, moentryList, bangid, analogCalcVersion, isChangePriority, planCheck, IsWeekPlan);
  5107. }
  5108. else
  5109. {
  5110. return "未查找到对应的计划工单,请联系管理员。";
  5111. }
  5112. return "ok";
  5113. }
  5114. //找到没有关闭的PR,做数量的减少
  5115. public srm_pr_main RerunPr(srm_pr_main pr, List<srm_pr_main> referlist)
  5116. {
  5117. //如果当前PR已经关闭,则检查合并数据
  5118. if (pr.state == 0)
  5119. {
  5120. //已关闭,并且没有关联数据,则代表转PO了。
  5121. var refPr = referlist.Find(s => s.pr_billno == pr.refer_pr_billno);
  5122. //如果有关联,继续往下查
  5123. if (refPr != null)
  5124. {
  5125. return RerunPr(refPr, referlist);
  5126. }
  5127. else
  5128. {
  5129. return null;
  5130. }
  5131. }
  5132. else
  5133. {
  5134. return pr;
  5135. }
  5136. }
  5137. /// <summary>
  5138. /// 递归寻找PR,找到合并后的PR
  5139. /// </summary>
  5140. public void RecursionGetDbPr2(List<srm_pr_main> list, List<srm_pr_main> referlist)
  5141. {
  5142. List<srm_pr_main> prlist = _mysql_srm_pr_main.GetListAsync(s => list.Select(c => c.refer_pr_billno).Contains(s.pr_billno)).Result;
  5143. if (prlist.Any())
  5144. {
  5145. referlist.AddRange(prlist);
  5146. RecursionGetDbPr2(prlist, referlist);
  5147. }
  5148. }
  5149. /// <summary>
  5150. /// 工单检查物料齐套
  5151. /// </summary>
  5152. /// <param name="input"></param>
  5153. public async Task<PschedDto> OrderKittingCheck(List<mes_morder> mo_Mes_Morders, List<mes_moentry> moentryList, long bangid, string analogCalcVersion, bool isChangePriority, bool planCheck = false, bool IsWeekPlan = false)
  5154. {
  5155. //资源检查结果
  5156. PschedDto rtn = new PschedDto();
  5157. //资源检查明细list
  5158. List<ExamineResult> examines = new List<ExamineResult>();
  5159. OrderCheckDto input = new OrderCheckDto();
  5160. if (mo_Mes_Morders.Any())
  5161. {
  5162. input.company_id = mo_Mes_Morders[0].company_id;
  5163. input.factoryId = mo_Mes_Morders[0].factory_id.GetValueOrDefault();
  5164. }
  5165. //资源检查入参全局变量赋值
  5166. param.company_id = input.company_id;
  5167. param.factoryId = input.factoryId;
  5168. param.checkflag = false;
  5169. param.checkPlan = planCheck;
  5170. if (!string.IsNullOrEmpty(analogCalcVersion) && analogCalcVersion != "week")
  5171. {
  5172. _CalcBomViewAppService.LongPeriod = true;
  5173. }
  5174. /*List<mo_mes_morder> mo_Mes_Morders = _mes_morder.GetManyByCondition(x => x.start_time > DateTime
  5175. .Now.Date.AddDays(1) && x.start_time < DateTime
  5176. .Now.Date.AddDays(input.Day) && x.morder_state == MorderEnum.Initial_state && !x.IsDeleted && x.tenant_id == param.tenantId && x.bang_id == bangid).Result;
  5177. List<mo_mes_moentry> mo_Mes_Moentries = _mes_moentry.GetManyByCondition(x=> mo_Mes_Morders.Select(s => s.id).Contains(x.moentry_moid.Value)).Result;*/
  5178. var morderIdList = mo_Mes_Morders.Select(s => s.Id).ToList();
  5179. //List<mes_moentry> mo_Mes_Moentries = _mysql_mes_moentry.GetListAsync(x => morderIdList.Contains(x.moentry_moid.Value)).Result;
  5180. List<mes_moentry> mo_Mes_Moentries = moentryList;
  5181. //获取订单行数据
  5182. List<crm_seorderentry> sentrys = _mysql_crm_seorderentry.GetListAsync(p => p.factory_id == input.factoryId && !p.IsDeleted && mo_Mes_Moentries.Select(x => x.soentry_id).Contains(p.Id)).Result;
  5183. //删除同步Mysql后旧数据
  5184. await DeleteMySqlOldData(sentrys);
  5185. List<mo_ic_bom> boms = _ic_bom.GetListAsync(p => mo_Mes_Morders.Select(m => m.bom_number).Distinct().ToList().Contains(p.bom_number) && p.factory_id == input.factoryId && !p.IsDeleted).Result.ToList();
  5186. //物料bom
  5187. List<mo_ic_bom> bomlist = new List<mo_ic_bom>();
  5188. //物料bom明细
  5189. List<mo_ic_bom_child> bomchildlist = new List<mo_ic_bom_child>();
  5190. //物料信息
  5191. List<mo_ic_item> icitemlist = new List<mo_ic_item>();
  5192. //替代关系
  5193. List<mo_ic_substitute> sublist = new List<mo_ic_substitute>();
  5194. List<mo_ic_substitute_group> suballlist = new List<mo_ic_substitute_group>();
  5195. List<mo_ic_substitute_group_detail> subdtllist = new List<mo_ic_substitute_group_detail>();
  5196. //物料库存表
  5197. List<mo_ic_item_stock> stocklist = new List<mo_ic_item_stock>();
  5198. //物料占用记录
  5199. List<mo_ic_item_stockoccupy> sklist = new List<mo_ic_item_stockoccupy>();
  5200. //sorder=null 是因为齐套检查不需要生成工单、采购、委外等信息,所以不需要关联的工单信息传递进去。
  5201. var pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).Distinct().ToList().Contains(s.sourceid)).Result;
  5202. List<mo_ic_bom> autoCreates = new List<mo_ic_bom>();
  5203. boms.ForEach(p =>
  5204. {
  5205. if (!pretreatments.Where(s => s.sourceid == p.mysql_id).Any())
  5206. {
  5207. autoCreates.Add(p);
  5208. }
  5209. });
  5210. if (autoCreates.Any())
  5211. {
  5212. AutoCreateBomBill(param.company_id.ToString(), autoCreates);
  5213. pretreatments = _mysql_b_bom_pretreatment.GetListAsync(s => boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
  5214. }
  5215. //增加特殊工单的预处理结果,因为特殊工单是自定义物料清单
  5216. List<string> tsWork = new List<string> { "试制工单", "返工工单" };
  5217. var specialWork = mo_Mes_Morders.Where(x => tsWork.Contains(x.morder_type)).ToList();
  5218. pretreatments.AddRange(_mysql_b_bom_pretreatment.GetListAsync(s => specialWork.Select(c => c.Id).ToList().Contains(s.sourceid)).Result);
  5219. List<string> itemNums = new List<string>();
  5220. //计算需求
  5221. List<AlignmentCalcDto> AlignmentCalcList = new List<AlignmentCalcDto>();
  5222. if (IsWeekPlan)
  5223. {
  5224. var locationRange = _configurationItem.Select(x => x.FldName == "MRPLocationRange" && x.Domain == param.factoryId.ToString()).FirstOrDefault();
  5225. List<string> locationList = new List<string> { "1000", "1001", "5008", "8000", "8001" };
  5226. if (locationRange != null && locationRange.Val != null)
  5227. {
  5228. locationList = locationRange.Val.SplitToArray(",").ToList();
  5229. }
  5230. List<string> nbrType = new List<string> { "SM", "OA", "IA" };
  5231. var nbrList = _nbrMaster.Select(x => x.Domain == param.factoryId.ToString() && nbrType.Contains(x.Type) && x.Status.ToUpper() != "C").ToList();
  5232. if (nbrList.Any())
  5233. {
  5234. var nbrDtlList = _nbrDetail.Select(x => nbrList.Select(c => c.RecID).Contains(x.NbrRecID) && locationList.Contains(x.LocationFrom) && x.Status.ToUpper() != "C" && x.IsActive).ToList();
  5235. if (nbrDtlList.Any())
  5236. {
  5237. nbrDtlList.ForEach(x =>
  5238. {
  5239. if (x.QtyOrd - x.QtyRec > 0)
  5240. {
  5241. var dto = AlignmentCalcList.Find(s => s.ItemNum == x.ItemNum);
  5242. if (dto == null)
  5243. {
  5244. dto = new AlignmentCalcDto();
  5245. dto.ItemNum = x.ItemNum;
  5246. AlignmentCalcList.Add(dto);
  5247. }
  5248. dto.NeedQty += x.QtyOrd - x.QtyRec;
  5249. }
  5250. });
  5251. }
  5252. }
  5253. //退料单逻辑相反
  5254. var wodNbrList = _nbrMaster.Select(x => x.Domain == param.factoryId.ToString() && x.Type == "WOD" && x.Status.ToUpper() != "C").ToList();
  5255. if (wodNbrList.Any())
  5256. {
  5257. //WOD是退料
  5258. var wodNbrDtlList = _nbrDetail.Select(x => wodNbrList.Select(c => c.RecID).Contains(x.NbrRecID) && locationList.Contains(x.LocationTo) && x.Status.ToUpper() != "C" && x.IsActive).ToList();
  5259. if (wodNbrDtlList.Any())
  5260. {
  5261. wodNbrDtlList.ForEach(x =>
  5262. {
  5263. if (x.QtyOrd - x.QtyRec > 0)
  5264. {
  5265. var dto = AlignmentCalcList.Find(s => s.ItemNum == x.ItemNum);
  5266. if (dto == null)
  5267. {
  5268. dto = new AlignmentCalcDto();
  5269. dto.ItemNum = x.ItemNum;
  5270. AlignmentCalcList.Add(dto);
  5271. }
  5272. dto.NeedQty -= x.QtyOrd - x.QtyRec;
  5273. }
  5274. });
  5275. }
  5276. }
  5277. itemNums.AddRange(AlignmentCalcList.Select(x => x.ItemNum));
  5278. }
  5279. var pretreatList = pretreatments.Select(x => x.item_number).Distinct().ToList();
  5280. itemNums.AddRange(pretreatList);
  5281. await AsyncItemStockFromWMS(itemNums, analogCalcVersion);
  5282. //数据库快照-同步mysql库数据到mongoDB中
  5283. await DbSnapShot(input.company_id, input.factoryId, bangid, pretreatments, analogCalcVersion);
  5284. DataInitialization(boms, bangid, icitemlist, stocklist, pretreatments, sklist);
  5285. _CalcBomViewAppService.param = param;
  5286. List<string> GenerateMoList = new List<string>();
  5287. var moNbrlistDto = _serialNumberAppService.GetBillNo(input.factoryId.ToString(), "M5", mo_Mes_Morders.Count, "", 1);
  5288. if (moNbrlistDto.Any())
  5289. {
  5290. foreach (var nbr in moNbrlistDto)
  5291. {
  5292. GenerateMoList.Add(nbr.NbrResult);
  5293. }
  5294. }
  5295. _CalcBomViewAppService.GenerateMoList = GenerateMoList;
  5296. _CalcBomViewAppService.newStockOccList = new List<mo_ic_item_stockoccupy>();
  5297. foreach (var item in mo_Mes_Morders)
  5298. {
  5299. var moentry = mo_Mes_Moentries.Find(s => s.moentry_moid == item.Id);
  5300. if (moentry == null)
  5301. {
  5302. continue;
  5303. }
  5304. var sentry = sentrys.Find(s => s.Id == moentry.soentry_id);
  5305. //工单资源检查信息
  5306. ExamineResult dtl = new ExamineResult();
  5307. dtl.morder_id = item.Id;
  5308. dtl.morder_no = item.morder_no;
  5309. dtl.bangid = bangid;
  5310. dtl.order_statr_time = item.start_time;
  5311. dtl.bom_number = item.bom_number;
  5312. dtl.need_qty = item.need_number.GetValueOrDefault();
  5313. //获取当前物料bom数据
  5314. //var childBom = boms.Where(p => p.bom_number == item.bom_number).FirstOrDefault();
  5315. //获取当前物料bom数据
  5316. List<b_bom_pretreatment> itemPrelist = new List<b_bom_pretreatment>();
  5317. //通过工单ID读取,考虑特殊工单的预处理
  5318. itemPrelist = pretreatments.Where(s => s.sourceid == item.Id).ToList();
  5319. if (!itemPrelist.Any())
  5320. {
  5321. var childBom = boms.Where(p => p.bom_number == item.bom_number).FirstOrDefault();
  5322. if (childBom != null)
  5323. {
  5324. itemPrelist = pretreatments.Where(s => s.sourceid == childBom.mysql_id).ToList();
  5325. }
  5326. else
  5327. {
  5328. continue;
  5329. }
  5330. }
  5331. if (!itemPrelist.Any())
  5332. {
  5333. continue;
  5334. }
  5335. var getBomList = ObjectMapper.Map<List<b_bom_pretreatment>, List<BomChildExamineDto>>(itemPrelist);
  5336. if (sentry != null)
  5337. {
  5338. dtl.sentry_id = sentry.Id;
  5339. getBomList.ForEach(s => s.sentry_id = item.Id);
  5340. }
  5341. _CalcBomViewAppService.mes_morder = item;
  5342. _CalcBomViewAppService.morder_type = item.morder_type;
  5343. //库存初始化
  5344. _CalcBomViewAppService.BomStock(getBomList, stocklist, bangid);
  5345. //计算
  5346. _CalcBomViewAppService.CalcView(getBomList, bangid, item.need_number.GetValueOrDefault(), item.moentry_sys_stime, sklist, sentry, icitemlist);
  5347. //TODO:最晚开始时间
  5348. //var curFacDtl = leadTimeList.FirstOrDefault(p => p.item_id == childBom.icitem_id);
  5349. //物料齐套时间
  5350. dtl.kitting_times = getBomList.Where(p => p.is_use && p.kitting_time != null).OrderByDescending(m => m.kitting_time).First().kitting_time.GetValueOrDefault();
  5351. //替代关系展开list
  5352. dtl.BomChildExamineList = getBomList;
  5353. //添加订单行开工信息
  5354. examines.Add(dtl);
  5355. }
  5356. rtn.examines = examines;
  5357. if (planCheck)
  5358. {
  5359. //如果有计划工单,则需要生成pr po oo
  5360. List<mo_srm_pr_main> prmainlist = new List<mo_srm_pr_main>();
  5361. List<srm_pr_main> pr_mainlist = new List<srm_pr_main>();
  5362. if (_CalcBomViewAppService.SRMPRDtoList.Any())
  5363. {
  5364. List<List<mo_srm_pr_main>> prlist = _CalcBomViewAppService.SRMPRDtoList.Where(f => f.srm_Pr_Main != null).Select(s => s.srm_Pr_Main).ToList();
  5365. List<mo_srm_pr_main> list = new List<mo_srm_pr_main>();
  5366. foreach (var pr in prlist)
  5367. {
  5368. foreach (var item in pr)
  5369. {
  5370. list.Add(item);
  5371. prmainlist.Add(item);
  5372. }
  5373. }
  5374. if (list.Any())
  5375. rtn.srm_pr_list = _CalcBomViewAppService.SRMPRDtoList;
  5376. }
  5377. if (prmainlist.Any())
  5378. {
  5379. var nbrlistDto = _serialNumberAppService.GetBillNo(prmainlist[0].factory_id.ToString(), "PR", prmainlist.Count, "admin", 1);
  5380. int index = 0;
  5381. foreach (var p in prmainlist)
  5382. {
  5383. if (nbrlistDto[index] != null)
  5384. {
  5385. p.pr_billno = nbrlistDto[index].NbrResult.ToString();
  5386. }
  5387. index++;
  5388. if (p.pr_purchaseid.GetValueOrDefault() == 0)
  5389. {
  5390. //数据丢失
  5391. var list = _mysql_srm_purchase.GetListAsync(s => s.icitem_id == p.icitem_id).Result;
  5392. if (list.Any())
  5393. {
  5394. var purchase = list.OrderBy(s => s.quota_priority).FirstOrDefault();
  5395. p.pr_purchaseid = purchase.supplier_id;
  5396. p.pr_purchasename = purchase.supplier_name;
  5397. p.pr_purchasenumber = purchase.supplier_number;
  5398. }
  5399. }
  5400. }
  5401. pr_mainlist = ObjectMapper.Map<List<mo_srm_pr_main>, List<srm_pr_main>>(prmainlist);
  5402. pr_mainlist.ForEach(a => { a.analogcalcversion = analogCalcVersion; });
  5403. }
  5404. //暂时屏蔽重新生成工单物料明细
  5405. List<WorkOrdDetail> mainWorkOrdDetails = new List<WorkOrdDetail>();
  5406. List<WorkOrdDetail> delWorkOrddetails = new List<WorkOrdDetail>();
  5407. //获取物料主数据
  5408. List<ItemMaster> itemMasters = _itemMaster.Select(p => p.Domain == param.factoryId.ToString()).ToList();
  5409. //成品虚拟件对应关系
  5410. var productOpList = _productStructureOp.Select(x => mo_Mes_Morders.Select(c => c.product_code).Contains(x.ProductItem) && x.Domain == param.factoryId.ToString());
  5411. var workOrds = _workOrdMaster.Select(a => mo_Mes_Morders.Select(p => p.morder_no).ToList().Contains(a.WorkOrd) && a.Domain == param.factoryId.ToString() && a.IsActive);
  5412. delWorkOrddetails = _workOrdDetail.Select(x => workOrds.Select(c => c.RecID).Contains((int)x.WorkOrdMasterRecID) && x.Domain == param.factoryId.ToString());
  5413. foreach (var workord in mo_Mes_Morders)
  5414. {
  5415. long fid = GetParentMo(mo_Mes_Morders, workord);
  5416. var exm = examines.Find(s => s.morder_id == fid);
  5417. //var exm = examines.Find(s => s.morder_no == workord.morder_no);
  5418. if (exm != null)
  5419. {
  5420. var childs = exm.BomChildExamineList.Where(s => s.is_use == true).ToList();
  5421. var child = childs.Find(s => s.item_number == workord.product_code);
  5422. if (workord.morder_type == "返工工单")
  5423. {
  5424. child = childs.Find(s => s.item_number == workord.product_code && s.level == 1);
  5425. }
  5426. if (child == null)
  5427. {
  5428. continue;
  5429. }
  5430. List<BomChildExamineDto> returnList = new List<BomChildExamineDto>();
  5431. var productOps = productOpList.Where(x => x.ProductItem == workord.product_code).ToList();
  5432. GetWorkDetalis(childs.Where(s => s.parent_id == child.fid).ToList(), returnList, childs, productOps);
  5433. if (returnList.Any())
  5434. {
  5435. WorkOrdDetail woDetail = null;
  5436. var calereturnList = returnList.OrderBy(c => c.item_number).Select(x => x.item_number).Distinct().ToList();
  5437. var work = workOrds.Find(x => x.WorkOrd == workord.morder_no);
  5438. if (work == null)
  5439. {
  5440. continue;
  5441. }
  5442. short num = 1;
  5443. foreach (var caleNumber in calereturnList)
  5444. {
  5445. var caleList = returnList.Where(x => x.item_number == caleNumber).ToList();
  5446. var itmeMst = itemMasters.Find(x => x.ItemNum == caleNumber);
  5447. //添加工单的物料信息
  5448. woDetail = new WorkOrdDetail();
  5449. woDetail.Domain = workord.factory_id.ToString();
  5450. woDetail.WorkOrd = workord.morder_no;
  5451. var oplist = caleList.Where(x => x.Op > 0).ToList();
  5452. woDetail.Op = 0;
  5453. if (oplist.Any())
  5454. {
  5455. woDetail.Op = oplist.Min(f => f.Op);
  5456. }
  5457. woDetail.ItemNum = caleNumber;
  5458. woDetail.QtyPosted = 0m;
  5459. woDetail.QtyReturned = 0m;
  5460. woDetail.Status = "";
  5461. woDetail.IsActive = true;
  5462. woDetail.CreateTime = DateTime.Now;
  5463. woDetail.Line = num;
  5464. woDetail.QtyRequired = caleList.Sum(c => c.needCount);
  5465. woDetail.WorkOrdMasterRecID = work.RecID;
  5466. woDetail.Location = itmeMst == null ? "" : itmeMst.Location;
  5467. if (workord.need_number != 0)
  5468. {
  5469. woDetail.FrozenBOMQty = Math.Round(woDetail.QtyRequired / workord.need_number.GetValueOrDefault(), 10);
  5470. }
  5471. mainWorkOrdDetails.Add(woDetail);
  5472. num++;
  5473. }
  5474. }
  5475. }
  5476. }
  5477. List<srm_pr_main> updatPrList = new List<srm_pr_main>();
  5478. List<srm_pr_main> deletePrList = new List<srm_pr_main>();
  5479. List<srm_pr_main> addPrList = new List<srm_pr_main>();
  5480. List<GenerateMorderDto> generateMorderDtos = new List<GenerateMorderDto>();
  5481. if (IsWeekPlan)
  5482. {
  5483. foreach (var exami in examines)
  5484. {
  5485. exami.BomChildExamineList.ForEach(x =>
  5486. {
  5487. if ((x.erp_cls == 2 || x.erp_cls == 3) && x.is_use)
  5488. {
  5489. var dto = AlignmentCalcList.Find(s => s.ItemNum == x.item_number);
  5490. if (dto == null)
  5491. {
  5492. dto = new AlignmentCalcDto();
  5493. dto.ItemNum = x.item_number;
  5494. AlignmentCalcList.Add(dto);
  5495. }
  5496. dto.NeedQty += x.needCount;
  5497. }
  5498. else if ((x.erp_cls == 1 && x.level != 1) && x.is_use && (x.make_qty > 0 || (x.sqty == 0 && x.security_stock > 0)))
  5499. {
  5500. var mos = generateMorderDtos.Where(m => m.BomNumber == x.item_number).ToList();
  5501. //需求数总和
  5502. if (mos.Count > 0)
  5503. {
  5504. mos[0].Quantity += x.make_qty;
  5505. //补充安全库存数量
  5506. if (x.sqty == 0)
  5507. {
  5508. mos[0].ReplenishQty = x.security_stock;
  5509. }
  5510. }
  5511. else
  5512. {
  5513. GenerateMorderDto generateMorderDto = new GenerateMorderDto()
  5514. {
  5515. seorderentry = null,
  5516. seorder = null,
  5517. ic_Item = icitemlist.Find(s => s.mysql_id == x.item_id),
  5518. BomNumber = x.item_number,
  5519. version = x.version,
  5520. number = x.item_number,
  5521. Quantity = x.make_qty,
  5522. morder_type = MorderEnum.JhMorder,
  5523. work_order_type = MorderEnum.CgMorder,
  5524. morder_state = MorderEnum.Initial_state,
  5525. ParentId = exami.morder_id,
  5526. bang_id = bangid,
  5527. morder_no = null
  5528. };
  5529. generateMorderDtos.Add(generateMorderDto);
  5530. }
  5531. }
  5532. });
  5533. }
  5534. //if (generateMorderDtos.Any())
  5535. //{
  5536. // generateMorderDtos.ForEach(m => {
  5537. // //补安全库存
  5538. // m.Quantity = m.Quantity.GetValueOrDefault() + m.ReplenishQty.GetValueOrDefault();
  5539. // //创建子料工单
  5540. // _morderAppService.param = param;
  5541. // Mes_MorderDto mes_MorderDto = _morderAppService.GenerateMorder(m);
  5542. // if (mes_MorderDto != null)
  5543. // {
  5544. // ProdExamineParamDto prodExamine = new ProdExamineParamDto()
  5545. // {
  5546. // ItemNum = m.number,
  5547. // PlanStart = DateTime.Now,
  5548. // QtyOrd = m.Quantity.GetValueOrDefault(),
  5549. // Domain = param.factoryId.ToString()
  5550. // };
  5551. // _productExamineAppService.routingOps = routingOps;
  5552. // int make = _productExamineAppService.ProductTime(prodExamine);
  5553. // mes_MorderDto.mes_Morders[0].moentry_sys_etime = DateTime.Now.AddDays(-1 - m.ic_Item.PurLT);
  5554. // mes_MorderDto.mes_Morders[0].moentry_sys_stime = mes_MorderDto.mes_Morders[0].moentry_sys_etime.GetValueOrDefault().AddDays(-(make - 1));
  5555. // _CalcBomViewAppService.mordersInsertList.AddRange(mes_MorderDto.mes_Morders);
  5556. // _CalcBomViewAppService.moentriesInsertList.AddRange(mes_MorderDto.mes_Moentries);
  5557. // }
  5558. // });
  5559. //}
  5560. var ic_items = _mysql_ic_item.GetListAsync(x => AlignmentCalcList.Select(c => c.ItemNum).Contains(x.number)).Result;
  5561. //库存
  5562. var dbitemstockList = _mysql_ic_item_stock.GetListAsync(a => AlignmentCalcList.Select(x => x.ItemNum).Contains(a.icitem_number) && a.factory_id == param.factoryId).Result;
  5563. //获取PR和PO
  5564. var DBprmainList = _mysql_srm_pr_main.GetListAsync(x => x.factory_id == param.factoryId && x.state != 0 && x.state != 4 && string.IsNullOrEmpty(x.analogcalcversion) == true && ic_items.Select(a => a.Id).Contains(x.icitem_id.GetValueOrDefault())).Result;
  5565. //货源清单
  5566. var dbPurchaseList = _mysql_srm_purchase.GetListAsync(x => x.factory_id == param.factoryId && x.quota_rate.GetValueOrDefault() > 0 && AlignmentCalcList.Select(c => c.ItemNum).Contains(x.number)).Result;
  5567. //PO、DO
  5568. var purordmstList = _PurOrdMaster.Select(x => string.IsNullOrEmpty(x.Status) && x.Status.ToUpper() != "C").ToList();
  5569. //过滤PO、DO:
  5570. //1、PO只有采购组为110,160的采购订单能使用
  5571. //2、DO只有供应类别为"标准"或"VMI"的才能使用
  5572. List<PurOrdMaster> newPurMasters = new List<PurOrdMaster>();
  5573. var kyPoList = purordmstList.Where(p => !p.PurOrd.StartsWith("DO") && (p.Buyer == "110" || p.Buyer == "160" || p.Buyer == "170")).ToList();
  5574. if (kyPoList.Any())
  5575. {
  5576. newPurMasters.AddRange(kyPoList);
  5577. }
  5578. var kyDoList = purordmstList.Where(p => p.PurOrd.StartsWith("DO") && (p.USAGE == "标准" || p.USAGE == "VMI" || p.USAGE == "委外加工")).ToList();
  5579. if (kyDoList.Any())
  5580. {
  5581. newPurMasters.AddRange(kyDoList);
  5582. }
  5583. purordmstList = newPurMasters;
  5584. //过滤采购单明细
  5585. var purorddtlList = new List<PurOrdDetail>();
  5586. if (purordmstList.Any())
  5587. {
  5588. purorddtlList = _PurOrdDetail.Select(x => purordmstList.Select(a => a.PurOrd).Contains(x.PurOrd) && x.QtyOrded - x.RctQty > 0 && string.IsNullOrEmpty(x.Status) && x.Status.ToUpper() != "C").ToList();
  5589. }
  5590. AlignmentCalcList.ForEach(x =>
  5591. {
  5592. var stock = dbitemstockList.Find(c => c.icitem_number == x.ItemNum);
  5593. if (stock != null)
  5594. {
  5595. x.InventoryQty += stock.sqty.GetValueOrDefault();
  5596. }
  5597. var supplist = dbPurchaseList.Where(s => s.number == x.ItemNum).ToList();
  5598. if (DBprmainList.Any() || prmainlist.Any())
  5599. {
  5600. var icitem = ic_items.Find(a => a.number == x.ItemNum);
  5601. if (icitem != null)
  5602. {
  5603. x.ProcureQty += DBprmainList.Where(a => a.icitem_id == icitem.Id).Sum(c => c.pr_aqty.GetValueOrDefault());
  5604. x.ProcureQty += prmainlist.Where(a => a.icitem_id == icitem.Id).Sum(c => c.pr_aqty.GetValueOrDefault());
  5605. }
  5606. }
  5607. List<PurOrdMaster> curpurordmstList = new List<PurOrdMaster>();
  5608. if (purordmstList.Any())
  5609. {
  5610. //根据货源清单过滤
  5611. curpurordmstList = purordmstList.Where(p => supplist.Select(s => s.supplier_number).ToList().Contains(p.Supp)).ToList();
  5612. }
  5613. if (curpurordmstList.Any() && purorddtlList.Any())
  5614. {
  5615. x.ProcureQty += purorddtlList.Where(a => a.ItemNum == x.ItemNum && curpurordmstList.Select(c => c.PurOrd).ToList().Contains(a.PurOrd)).Sum(c => c.QtyOrded - c.RctQty);
  5616. }
  5617. //差异数量=工单需求总数-库存数量-PR、PO采购在途数量
  5618. x.DifferenceQty = x.NeedQty - x.InventoryQty - x.ProcureQty;
  5619. });
  5620. //需要增加PR的集合
  5621. var prAddList = AlignmentCalcList.Where(x => x.DifferenceQty > 0).ToList();
  5622. //需要减少PR的集合
  5623. var prDelList = AlignmentCalcList.Where(x => x.DifferenceQty < 0).ToList();
  5624. //获取需要新增的PR
  5625. var sysSet = _generalizedCodeMaster.Select(s => s.FldName == "SystemConfig" && s.Val == "ScheduleAgreement" && s.Domain == param.factoryId.ToString()).ToList();
  5626. int ScheduleAgreement = 0;//计划协议 0不启用,1启用
  5627. if (sysSet.Any())
  5628. {
  5629. if (!string.IsNullOrEmpty(sysSet[0].Ufld1))
  5630. {
  5631. int.TryParse(sysSet[0].Ufld1, out ScheduleAgreement);
  5632. }
  5633. }
  5634. //需要新增的PR集合
  5635. addPrList = CalcPrAdd(prAddList, dbPurchaseList, ic_items, ScheduleAgreement);
  5636. if (addPrList.Any())
  5637. {
  5638. var addPrlistDto = _serialNumberAppService.GetBillNo(param.factoryId.ToString(), "PR", addPrList.Count, "admin", 1);
  5639. int index = 0;
  5640. foreach (var p in addPrList)
  5641. {
  5642. if (addPrlistDto[index] != null)
  5643. {
  5644. p.pr_billno = addPrlistDto[index].NbrResult.ToString();
  5645. }
  5646. index++;
  5647. }
  5648. }
  5649. //数据库需要减少的PR集合
  5650. CalcPrDel(prDelList, dbPurchaseList, ic_items, DBprmainList.Where(x => x.state == 1).ToList(), updatPrList, deletePrList, pr_mainlist);//只取新增状态的PR,可以做删除或者修改
  5651. new NLogHelper("AlignmentCalcList").WriteLog("AlignmentCalcList", JsonConvert.SerializeObject(AlignmentCalcList), _currentTenant.Id.ToString());
  5652. }
  5653. using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
  5654. {
  5655. try
  5656. {
  5657. _businessDbContext.UpdateRange(mo_Mes_Morders);
  5658. //长周期都是成品检查,生成的都是中间件工单,不需要写入;周计划包含中间件工单,需要写入
  5659. //长周期也需要写入,加字段版本区分
  5660. if (_CalcBomViewAppService.mordersInsertList.Any())
  5661. {
  5662. var molist = ObjectMapper.Map<List<mo_mes_morder>, List<mes_morder>>(_CalcBomViewAppService.mordersInsertList);
  5663. var moentrylist = ObjectMapper.Map<List<mo_mes_moentry>, List<mes_moentry>>(_CalcBomViewAppService.moentriesInsertList);
  5664. molist.ForEach(a => { a.analogcalcversion = analogCalcVersion; });
  5665. await _businessDbContext.AddRangeAsync(molist);
  5666. List<WorkOrdMaster> workOrdSave = new List<WorkOrdMaster>();
  5667. List<WorkOrdRouting> workOrdRoutingSave = new List<WorkOrdRouting>();
  5668. List<WorkOrdDetail> workOrdDetails = new List<WorkOrdDetail>();
  5669. if (molist.Any())
  5670. {
  5671. molist.ForEach(s => { s.create_time = DateTime.Now; s.factory_id = input.factoryId; s.company_id = input.company_id; });
  5672. //同步工单
  5673. CreateWorkOrdDates(molist, moentrylist, routingOps, workOrdSave, workOrdRoutingSave, workOrdDetails, new List<b_examine_result>(), new List<b_bom_child_examine>());
  5674. if (workOrdSave.Any())
  5675. {
  5676. workOrdSave.ForEach(a => { a.AnalogCalcVersion = analogCalcVersion; });
  5677. await _businessDbContext.AddRangeAsync(workOrdSave);
  5678. //CalcPriority(input.factoryId.ToString());
  5679. RefreshPriority(null, input.factoryId.ToString());
  5680. }
  5681. var DBworkOrdList = _workOrdMaster.Select(a => workOrdSave.Count > 0 && a.Domain == workOrdSave[0].Domain && workOrdSave.Select(c => c.WorkOrd).Contains(a.WorkOrd));
  5682. if (workOrdRoutingSave.Any())
  5683. {
  5684. workOrdRoutingSave.ForEach(c =>
  5685. {
  5686. c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
  5687. });
  5688. await _businessDbContext.AddRangeAsync(workOrdRoutingSave);
  5689. }
  5690. if (workOrdDetails.Any())
  5691. {
  5692. workOrdDetails.ForEach(c =>
  5693. {
  5694. c.WorkOrdMasterRecID = DBworkOrdList.Where(a => a.WorkOrd == c.WorkOrd).First().RecID;
  5695. });
  5696. await _businessDbContext.AddRangeAsync(workOrdDetails);
  5697. }
  5698. }
  5699. }
  5700. if (_CalcBomViewAppService.moentriesInsertList.Any() && string.IsNullOrEmpty(analogCalcVersion))
  5701. {
  5702. var moentrylist = ObjectMapper.Map<List<mo_mes_moentry>, List<mes_moentry>>(_CalcBomViewAppService.moentriesInsertList);
  5703. await _businessDbContext.AddRangeAsync(moentrylist);
  5704. }
  5705. if (pr_mainlist.Any())
  5706. {
  5707. await _businessDbContext.AddRangeAsync(pr_mainlist);
  5708. }
  5709. if (_CalcBomViewAppService.newStockOccList.Any())
  5710. {
  5711. var stockoccupylist = ObjectMapper.Map<List<mo_ic_item_stockoccupy>, List<ic_item_stockoccupy>>(_CalcBomViewAppService.newStockOccList);
  5712. stockoccupylist.ForEach(s => { s.GenerateNewId(help.NextId()); s.create_time = DateTime.Now; s.tenant_id = param.company_id.GetValueOrDefault(); s.company_id = param.company_id; s.factory_id = param.factoryId; });
  5713. await _businessDbContext.AddRangeAsync(stockoccupylist);
  5714. }
  5715. if (_CalcBomViewAppService.srm_Po_OccupiesInsert.Any())
  5716. {
  5717. _CalcBomViewAppService.srm_Po_OccupiesInsert.ForEach(s => { s.company_id = param.company_id; s.factory_id = param.factoryId; });
  5718. var srmpooccupyInsert = ObjectMapper.Map<List<mo_srm_po_occupy>, List<srm_po_occupy>>(_CalcBomViewAppService.srm_Po_OccupiesInsert);
  5719. srmpooccupyInsert.ForEach(x => { x.GenerateNewId(help.NextId()); });
  5720. await _businessDbContext.AddRangeAsync(srmpooccupyInsert);
  5721. }
  5722. if (delWorkOrddetails.Any())
  5723. {
  5724. _businessDbContext.BulkDelete(delWorkOrddetails);
  5725. }
  5726. if (mainWorkOrdDetails.Any())
  5727. {
  5728. await _businessDbContext.AddRangeAsync(mainWorkOrdDetails);
  5729. }
  5730. if (IsWeekPlan)
  5731. {
  5732. if (addPrList.Any())
  5733. {
  5734. await _businessDbContext.AddRangeAsync(addPrList);
  5735. }
  5736. if (updatPrList.Any())
  5737. {
  5738. _businessDbContext.UpdateRange(updatPrList);
  5739. }
  5740. if (deletePrList.Any())
  5741. {
  5742. await _mysql_srm_pr_main.HardDeleteAsync(deletePrList);
  5743. }
  5744. }
  5745. await unitOfWork.CompleteAsync();
  5746. }
  5747. catch (Exception e)
  5748. {
  5749. unitOfWork.Dispose();
  5750. new NLogHelper("ResourceExamineAppService").WriteLog("OrderKittingCheck", "工单检查数据更新失败:" + e.Message, _currentTenant.Id.ToString());
  5751. }
  5752. }
  5753. }
  5754. //检查结果写入数据库
  5755. await ExamineResultInsertDBAsync(examines);
  5756. //清空快照数据
  5757. await ClearSnapShot(bangid);
  5758. return rtn;
  5759. }
  5760. public void CalcPrDel(List<AlignmentCalcDto> prDelList, List<srm_purchase> purchase, List<ic_item> ic_items, List<srm_pr_main> dbPrlist, List<srm_pr_main> updatPrList, List<srm_pr_main> deletePrList, List<srm_pr_main> prmainlist)
  5761. {
  5762. prDelList.ForEach(dto =>
  5763. {
  5764. var itemPurList = purchase.Where(x => x.number == dto.ItemNum).ToList();
  5765. var icitem = ic_items.Find(x => x.number == dto.ItemNum);
  5766. if (itemPurList.Any() && icitem != null)
  5767. {
  5768. itemPurList.ForEach(c =>
  5769. {
  5770. //当前供应商需减少数量
  5771. decimal qty = Math.Floor(Math.Abs(dto.DifferenceQty) * c.quota_rate.GetValueOrDefault() / 100);
  5772. var MoItemSupplierList = prmainlist.Where(x => x.icitem_id == icitem.Id && x.pr_purchaseid == c.supplier_id).OrderByDescending(f => f.pr_sarrive_date).ToList();
  5773. if (MoItemSupplierList.Any())
  5774. {
  5775. foreach (var moPr in MoItemSupplierList)
  5776. {
  5777. if (moPr.pr_aqty > qty)//一个PR够减
  5778. {
  5779. moPr.pr_aqty = moPr.pr_aqty - qty;
  5780. moPr.pr_rqty = moPr.pr_aqty;
  5781. moPr.pr_sqty = moPr.pr_aqty;
  5782. dto.updateQty += qty;
  5783. qty = 0;
  5784. dto.updatePrlist.Add(moPr);
  5785. continue;
  5786. }
  5787. else if (moPr.pr_aqty == qty)//一个PR够减
  5788. {
  5789. dto.deleteQty += qty;
  5790. prmainlist.Remove(moPr);
  5791. qty = 0;
  5792. dto.deletePrlist.Add(moPr);
  5793. continue;
  5794. }
  5795. else
  5796. {
  5797. dto.deleteQty += moPr.pr_aqty.GetValueOrDefault();
  5798. qty -= moPr.pr_aqty.GetValueOrDefault();
  5799. prmainlist.Remove(moPr);
  5800. dto.deletePrlist.Add(moPr);
  5801. }
  5802. }
  5803. }
  5804. if (qty > 0)
  5805. {
  5806. //当前物料当前供应商的在途采购申请
  5807. var itemSupplierList = dbPrlist.Where(x => x.icitem_id == icitem.Id && x.pr_purchaseid == c.supplier_id).OrderByDescending(f => f.pr_sarrive_date).ToList();
  5808. if (itemSupplierList.Any())
  5809. {
  5810. foreach (var itemPr in itemSupplierList)
  5811. {
  5812. if (itemPr.pr_aqty > qty)//一个PR够减
  5813. {
  5814. itemPr.pr_aqty = itemPr.pr_aqty - qty;
  5815. itemPr.pr_rqty = itemPr.pr_aqty;
  5816. itemPr.pr_sqty = itemPr.pr_aqty;
  5817. updatPrList.Add(itemPr);
  5818. dto.updatePrlist.Add(itemPr);
  5819. dto.updateQty = qty;
  5820. qty = 0;
  5821. continue;
  5822. }
  5823. else if (itemPr.pr_aqty == qty)//一个PR够减
  5824. {
  5825. dto.deleteQty += qty;
  5826. deletePrList.Add(itemPr);
  5827. dto.deletePrlist.Add(itemPr);
  5828. qty = 0;
  5829. continue;
  5830. }
  5831. else
  5832. {
  5833. dto.deleteQty += itemPr.pr_aqty.GetValueOrDefault();
  5834. qty -= itemPr.pr_aqty.GetValueOrDefault();
  5835. deletePrList.Add(itemPr);
  5836. dto.deletePrlist.Add(itemPr);
  5837. }
  5838. if (qty == 0)
  5839. {
  5840. continue;
  5841. }
  5842. }
  5843. }
  5844. }
  5845. });
  5846. }
  5847. });
  5848. }
  5849. public List<srm_pr_main> CalcPrAdd(List<AlignmentCalcDto> prAddList, List<srm_purchase> purchase, List<ic_item> ic_items, int ScheduleAgreement)
  5850. {
  5851. List<srm_pr_main> prList = new List<srm_pr_main>();
  5852. prAddList.ForEach(dto =>
  5853. {
  5854. var itemPurList = purchase.Where(x => x.number == dto.ItemNum).ToList();
  5855. var icitem = ic_items.Find(x => x.number == dto.ItemNum);
  5856. foreach (var supplier in itemPurList)
  5857. {
  5858. srm_pr_main srm_Pr = new srm_pr_main();
  5859. srm_Pr.GenerateNewId(help.NextId());
  5860. srm_Pr.pr_order_type = icitem.erp_cls == 2 ? "L" : "";//单据类型
  5861. srm_Pr.supplier_type = supplier.supplier_type;
  5862. srm_Pr.IsRequireGoods = supplier.IsRequireGoods;
  5863. if (supplier.supplier_type == "VMI")
  5864. {
  5865. srm_Pr.IsRequireGoods = 1;
  5866. srm_Pr.pr_order_type = "K";
  5867. }
  5868. srm_Pr.pr_purchaseid = supplier.supplier_id;//供应商id
  5869. srm_Pr.pr_purchasenumber = supplier.supplier_number;//供应商编码
  5870. srm_Pr.pr_purchasename = supplier.supplier_name;//供应商名称
  5871. srm_Pr.pr_purchaser = supplier.order_rector_name;//采购员
  5872. srm_Pr.pr_purchaser_num = supplier.order_rector_num;//采购员工号(采购信息表)
  5873. srm_Pr.pr_rqty = Math.Ceiling(dto.DifferenceQty * supplier.quota_rate.GetValueOrDefault() / 100);//需求数量
  5874. srm_Pr.pr_aqty = srm_Pr.pr_rqty;//申请数量
  5875. srm_Pr.pr_sqty = srm_Pr.pr_rqty;//建议数量
  5876. srm_Pr.icitem_id = icitem.Id;//物料id
  5877. srm_Pr.icitem_name = icitem.name;//物料名称
  5878. //srm_Pr.num = returnlist.num;
  5879. if (ScheduleAgreement == 1)
  5880. {
  5881. supplier.lead_time = 7;//启用计划协议时,默认为7天。
  5882. srm_Pr.pr_ssend_date = DateTime.Now.Date.AddDays(1);//系统建议下单日期
  5883. srm_Pr.pr_sarrive_date = DateTime.Now.AddDays((double)supplier.lead_time.GetValueOrDefault());//系统建议到达日期(建议到货日期)
  5884. }
  5885. else
  5886. {
  5887. srm_Pr.pr_ssend_date = DateTime.Now.Date.AddDays(1);//系统建议下单日期
  5888. srm_Pr.pr_sarrive_date = DateTime.Now.Date.AddDays(1).AddDays((int)(Math.Ceiling(icitem.clean_leadtime.GetValueOrDefault() + icitem.self_inspection_date.GetValueOrDefault())));
  5889. }
  5890. srm_Pr.pr_sysprice = supplier.order_price;//系统价格(含税)
  5891. srm_Pr.pr_orderprice = srm_Pr.pr_rqty * supplier.order_price;//订单价格(含税)
  5892. srm_Pr.pr_price = supplier.netpurchase_price;//采购净价(不含税)
  5893. srm_Pr.pr_rate = supplier.taxrate;//税率
  5894. srm_Pr.pr_unit = icitem.unit;//单位
  5895. srm_Pr.state = 1;//状态
  5896. srm_Pr.old_apply_aqty = 0;//已申请数量
  5897. srm_Pr.pr_type = icitem.erp_cls == 2 ? 2 : 3;//申请类型
  5898. srm_Pr.currencytype = supplier.currency_type == null ? 1 : supplier.currency_type.Value;//币种
  5899. srm_Pr.secInv_ratio = icitem.secinv_ratio;//安全库存触发采购比例
  5900. srm_Pr.tenant_id = param.company_id;
  5901. srm_Pr.company_id = param.company_id;
  5902. srm_Pr.factory_id = param.factoryId;
  5903. srm_Pr.create_time = DateTime.Now;
  5904. srm_Pr.create_by_name = "admin";
  5905. srm_Pr.update_time = DateTime.Now;
  5906. srm_Pr.update_by_name = "admin";
  5907. prList.Add(srm_Pr);
  5908. dto.addPrlist.Add(srm_Pr);
  5909. }
  5910. });
  5911. return prList;
  5912. }
  5913. public async Task ExamineResultInsertDBAsync(List<ExamineResult> examines)
  5914. {
  5915. //检查结果写入数据库
  5916. List<b_examine_result> examineList = new List<b_examine_result>();
  5917. List<b_bom_child_examine> bomExamineList = new List<b_bom_child_examine>();
  5918. List<b_mo_occupy> mooccupyList = new List<b_mo_occupy>();
  5919. List<b_mo_order> moorderList = new List<b_mo_order>();
  5920. List<b_ooder> ooderList = new List<b_ooder>();
  5921. List<b_purchase> purchaseList = new List<b_purchase>();
  5922. List<b_purchase_occupy> purchaseoccupyList = new List<b_purchase_occupy>();
  5923. foreach (var ex in examines)
  5924. {
  5925. var b_ex = ObjectMapper.Map<ExamineResult, b_examine_result>(ex);
  5926. b_ex.GenerateNewId(help.NextId());// = help.NextId();
  5927. if (_CalcBomViewAppService.mordersInsertList.Any())
  5928. {
  5929. var sentryMo = _CalcBomViewAppService.mordersInsertList.Where(s => s.mysql_id == b_ex.morder_id).FirstOrDefault();
  5930. if (sentryMo != null)
  5931. {
  5932. b_ex.morder_id = sentryMo.mysql_id;
  5933. b_ex.morder_no = sentryMo.morder_no;
  5934. }
  5935. }
  5936. b_ex.create_time = DateTime.Now;
  5937. b_ex.company_id = param.company_id;
  5938. b_ex.tenant_id = param.company_id;
  5939. b_ex.factory_id = param.factoryId;
  5940. examineList.Add(b_ex);
  5941. ex.BomChildExamineList.ForEach(s =>
  5942. {
  5943. var bc_ex = ObjectMapper.Map<BomChildExamineDto, b_bom_child_examine>(s);
  5944. bc_ex.GenerateNewId(help.NextId());
  5945. bc_ex.examine_id = b_ex.Id;
  5946. bc_ex.company_id = param.company_id;
  5947. bc_ex.tenant_id = param.company_id;
  5948. bc_ex.factory_id = param.factoryId;
  5949. bc_ex.create_time = DateTime.Now;
  5950. bomExamineList.Add(bc_ex);
  5951. if (s.mo_occupy_list != null)
  5952. {
  5953. var olist = ObjectMapper.Map<List<mo_occupy>, List<b_mo_occupy>>(s.mo_occupy_list);
  5954. olist.ForEach(o =>
  5955. {
  5956. o.bom_child_examine_id = bc_ex.Id; o.company_id = param.company_id; o.tenant_id = param.company_id;
  5957. o.factory_id = param.factoryId;
  5958. });
  5959. mooccupyList.AddRange(olist);
  5960. }
  5961. if (s.make_list != null)
  5962. {
  5963. var mlist = ObjectMapper.Map<List<moorder>, List<b_mo_order>>(s.make_list);
  5964. mlist.ForEach(o =>
  5965. {
  5966. o.bom_child_examine_id = bc_ex.Id; o.company_id = param.company_id; o.tenant_id = param.company_id;
  5967. o.factory_id = param.factoryId;
  5968. });
  5969. moorderList.AddRange(mlist);
  5970. }
  5971. if (s.subcontracting_list != null)
  5972. {
  5973. var slist = ObjectMapper.Map<List<ooder>, List<b_ooder>>(s.subcontracting_list);
  5974. slist.ForEach(o =>
  5975. {
  5976. o.bom_child_examine_id = bc_ex.Id; o.company_id = param.company_id; o.tenant_id = param.company_id;
  5977. o.factory_id = param.factoryId;
  5978. });
  5979. ooderList.AddRange(slist);
  5980. }
  5981. if (s.purchase_list != null)
  5982. {
  5983. var plist = ObjectMapper.Map<List<purchase>, List<b_purchase>>(s.purchase_list);
  5984. plist.ForEach(o =>
  5985. {
  5986. o.bom_child_examine_id = bc_ex.Id; o.company_id = param.company_id; o.tenant_id = param.company_id;
  5987. o.factory_id = param.factoryId; o.create_time = DateTime.Now;
  5988. });
  5989. purchaseList.AddRange(plist);
  5990. }
  5991. if (s.purchase_occupy_list != null)
  5992. {
  5993. var purlist = ObjectMapper.Map<List<purchase_occupy>, List<b_purchase_occupy>>(s.purchase_occupy_list);
  5994. purlist.ForEach(o =>
  5995. {
  5996. o.bom_child_examine_id = bc_ex.Id; o.company_id = param.company_id; o.tenant_id = param.company_id;
  5997. o.factory_id = param.factoryId; o.create_time = DateTime.Now;
  5998. });
  5999. purchaseoccupyList.AddRange(purlist);
  6000. }
  6001. });
  6002. }
  6003. using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
  6004. {
  6005. try
  6006. {
  6007. if (examineList.Any())
  6008. {
  6009. _businessBangDbContext.BulkInsert(examineList);
  6010. }
  6011. if (bomExamineList.Any())
  6012. {
  6013. _businessBangDbContext.BulkInsert(bomExamineList.OrderBy(s => s.num_order).ToList());
  6014. }
  6015. if (mooccupyList.Any())
  6016. {
  6017. _businessBangDbContext.BulkInsert(mooccupyList);
  6018. }
  6019. if (moorderList.Any())
  6020. {
  6021. _businessBangDbContext.BulkInsert(moorderList);
  6022. }
  6023. if (ooderList.Any())
  6024. {
  6025. _businessBangDbContext.BulkInsert(ooderList);
  6026. }
  6027. if (purchaseList.Any())
  6028. {
  6029. _businessBangDbContext.BulkInsert(purchaseList);
  6030. }
  6031. if (purchaseoccupyList.Any())
  6032. {
  6033. _businessBangDbContext.BulkInsert(purchaseoccupyList);
  6034. }
  6035. await unitOfWork.CompleteAsync();
  6036. }
  6037. catch (Exception e)
  6038. {
  6039. new NLogHelper("ResourceExamineAppService").WriteLog("ReceiveResult", "资源检查计算结果相关数据更新失败:" + e.Message, _currentTenant.Id.ToString());
  6040. unitOfWork.Dispose();
  6041. }
  6042. }
  6043. }
  6044. /// <summary>
  6045. /// 删除旧订单行数据
  6046. /// </summary>
  6047. /// <param name="tenantId"></param>
  6048. /// <param name="factoryId"></param>
  6049. /// <param name="soentry_id"></param>
  6050. /// <returns></returns>
  6051. public async Task DeleteMySqlOldData(List<crm_seorderentry> soentry_id)
  6052. {
  6053. List<long> sentryids = soentry_id.Select(p => p.Id).ToList();
  6054. //删除工单相关表数据
  6055. /*var mes_moentry = _mysql_mes_moentry.GetListAsync(x => sentryids.Contains(x.soentry_id.Value)).Result;
  6056. var mes_morder = _mysql_mes_morder.GetListAsync(x => mes_moentry.Select(p => p.moentry_moid).ToList().Contains(x.Id)).Result;
  6057. if (mes_moentry.Count > 0)
  6058. {
  6059. await _mysql_mes_moentry.DeleteManyAsync(mes_moentry);
  6060. }
  6061. if (mes_morder.Count > 0)
  6062. {
  6063. await _mysql_mes_morder.DeleteManyAsync(mes_morder);
  6064. }*/
  6065. var mysql_mes_mooccupy = _mysql_mes_mooccupy.GetListAsync(x => soentry_id.Select(p => p.Id).Contains(x.moo_id_billid.Value)).Result;
  6066. if (mysql_mes_mooccupy.Count > 0)
  6067. {
  6068. await _businessDbContext.BulkDeleteAsync(mysql_mes_mooccupy);
  6069. }
  6070. /*var srm_pr_main = _mysql_srm_pr_main.GetListAsync(x => soentry_id.Select(p => p.Id).Contains(x.sentry_id.GetValueOrDefault())).Result;
  6071. if (srm_pr_main.Count > 0)
  6072. {
  6073. await _mysql_srm_pr_main.DeleteManyAsync(srm_pr_main);
  6074. }*/
  6075. /*var mes_oorders = _mysql_mes_oorder.GetListAsync(x => soentry_id.Select(p => p.Id).Contains(x.sentry_id.GetValueOrDefault())).Result;
  6076. if (mes_oorders.Count > 0)
  6077. {
  6078. await _mysql_mes_oorder.DeleteManyAsync(mes_oorders);
  6079. }*/
  6080. }
  6081. /// <summary>
  6082. /// 数据库快照
  6083. /// </summary>
  6084. /// <returns></returns>
  6085. public async Task DbSnapShot(long? companyId, long factoryId, long bangid, List<b_bom_pretreatment> pretreatments, string analogCalcVersion)
  6086. {
  6087. //TODO:申老师明确后续需要调整 根据需要使用的字段,来同步表数据。
  6088. //同步物料库存数据 根据预处理,来只找出部分数据同步。
  6089. List<long> itemIds = pretreatments.Select(s => s.item_id.GetValueOrDefault()).Distinct().ToList();
  6090. //var icitemStokc = _mysql_ic_item_stock.GetListAsync(p => p.tenant_id == tenantId && p.factory_id == factoryId).Result;
  6091. var icitemStokc = _mysql_ic_item_stock.GetListAsync(p => itemIds.Contains(p.icitem_id) && p.company_id == companyId).Result;
  6092. if (icitemStokc.Count > 0)
  6093. {
  6094. List<string> numbers = pretreatments.Select(s => s.item_number).Distinct().ToList();
  6095. var locationRange = _configurationItem.Select(x => x.FldName == "MRPLocationRange" && x.Domain == factoryId.ToString()).FirstOrDefault();
  6096. List<string> locationList = new List<string> { "1000", "1001", "5008", "8000", "8001" };
  6097. if (locationRange != null && locationRange.Val != null)
  6098. {
  6099. locationList = locationRange.Val.SplitToArray(",").ToList();
  6100. }
  6101. var locStock = _invMaster.Select(a => numbers.Contains(a.ItemNum) && a.IsActive && a.Domain == factoryId.ToString() && locationList.Contains(a.Location));
  6102. //var sapInvList = _SAPInv.Select(a => numbers.Contains(a.MATNR) && a.WERKS == factoryId.ToString() && (a.SOBKZ.ToUpper() == "O" || locationList.Contains(a.LGORT)));
  6103. //设置当前计算bangid
  6104. icitemStokc.ForEach(item =>
  6105. {
  6106. item.bang_id = bangid;
  6107. item.sqty = 0;
  6108. foreach (var lct in locationList)
  6109. {
  6110. var lctQty = locStock.Where(s => s.ItemNum == item.icitem_number && s.Location == lct).Sum(p => p.AvailStatusQty.GetValueOrDefault() + p.Assay.GetValueOrDefault());
  6111. //if (lctQty == 0)
  6112. //{
  6113. // lctQty = sapInvList.Where(x => x.MATNR == item.icitem_number && x.LGORT == lct).Sum(p => p.LABST + p.INSME);
  6114. //}
  6115. item.sqty += lctQty;
  6116. }
  6117. //if (!string.IsNullOrEmpty(analogCalcVersion))
  6118. //{
  6119. // item.sqty += sapInvList.Where(x => x.MATNR == item.icitem_number && x.SOBKZ.ToUpper() == "O").Sum(p => p.LABST + p.INSME);
  6120. //}
  6121. });
  6122. var moIcitemStokc = ObjectMapper.Map<List<ic_item_stock>, List<mo_ic_item_stock>>(icitemStokc);
  6123. moIcitemStokc.ForEach(item => { item.GenerateNewId(help.NextId()); item.create_time = DateTime.Now; });
  6124. //插入数据
  6125. await MongoHelper<mo_ic_item_stock>.InsertManyAsync(moIcitemStokc);
  6126. }
  6127. var workordmsters = new List<WorkOrdMaster>();
  6128. if (string.IsNullOrEmpty(analogCalcVersion))
  6129. {
  6130. //周计划屏蔽年度产生的工单
  6131. workordmsters = _workOrdMaster.Select(s => s.Domain == factoryId.ToString() && string.IsNullOrEmpty(s.Status) != true && s.Status.ToLower() != "c" && string.IsNullOrEmpty(s.AnalogCalcVersion));
  6132. }
  6133. else
  6134. {
  6135. workordmsters = _workOrdMaster.Select(s => s.Domain == factoryId.ToString() && string.IsNullOrEmpty(s.Status) != true && s.Status.ToLower() != "c");
  6136. }
  6137. if (workordmsters.Any())
  6138. {
  6139. //根据工单表找到工单明细,然后根据DOP工单占用记录,对比工单明细发货数量,来做冲销。
  6140. //var workdetails = _workOrdDetail.Select(s => workordmsters.Select(c => c.WorkOrd).Contains(s.WorkOrd));
  6141. List<ic_item_stockoccupy> item_occupy = new List<ic_item_stockoccupy>();
  6142. /*if (!param.checkPlan)
  6143. {
  6144. //在库检,只计算下达工单的占用。
  6145. var pwork = workordmsters.Where(x => x.Status.ToLower() == "r").ToList();
  6146. item_occupy = _mysql_ic_item_stockoccupy.GetListAsync(p => p.company_id == companyId && itemIds.Contains(p.icitem_id) && pwork.Select(c => c.WorkOrd).Contains(p.morder_mo)).Result;
  6147. }
  6148. else {
  6149. //物料库存占用记录表
  6150. item_occupy = _mysql_ic_item_stockoccupy.GetListAsync(p => p.company_id == companyId && itemIds.Contains(p.icitem_id) && workordmsters.Select(c => c.WorkOrd).Contains(p.morder_mo)).Result;
  6151. }*/
  6152. //不论计划还是在库检,都是按全量跑工单,所以每次计算已占用库存,只算下达工单的占用。
  6153. var pwork = workordmsters.Where(x => x.Status.ToLower() == "r").ToList();
  6154. item_occupy = _mysql_ic_item_stockoccupy.GetListAsync(p => p.company_id == companyId && itemIds.Contains(p.icitem_id) && pwork.Select(c => c.WorkOrd).Contains(p.morder_mo)).Result;
  6155. var nbrList = _nbrMaster.Select(x => pwork.Select(c => c.WorkOrd).Contains(x.WorkOrd) && x.Status.ToUpper() != "C").ToList();
  6156. if (nbrList.Any())
  6157. {
  6158. var nbrDtlList = _nbrDetail.Select(x => nbrList.Select(c => c.RecID).Contains(x.NbrRecID) && x.Status.ToUpper() != "C").ToList();
  6159. if (nbrDtlList.Any())
  6160. {
  6161. if (item_occupy.Any())
  6162. {
  6163. item_occupy.ForEach(s =>
  6164. {
  6165. //TODO:对发布数量和占用数量进行对冲,因为目前没有处理不同层级下使用相同物料的占用的问题。dop占用有项次号,而wms的发布数量明细没有项次号
  6166. var wdtl = nbrDtlList.Find(x => x.WorkOrd == s.morder_mo && x.ItemNum == s.icitem_number);
  6167. if (wdtl != null)
  6168. {
  6169. s.quantity = wdtl.QtyOrd - wdtl.QtyRec;
  6170. s.quantity = s.quantity < 0 ? 0 : s.quantity;
  6171. }
  6172. });
  6173. item_occupy = item_occupy.Where(s => s.quantity > 0).ToList();
  6174. if (item_occupy.Count > 0)
  6175. {
  6176. var mo_item_occupy = ObjectMapper.Map<List<ic_item_stockoccupy>, List<mo_ic_item_stockoccupy>>(item_occupy);
  6177. mo_item_occupy.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; });
  6178. await MongoHelper<mo_ic_item_stockoccupy>.InsertManyAsync(mo_item_occupy);
  6179. }
  6180. }
  6181. }
  6182. }
  6183. //工单主表
  6184. var mes_morder = _mysql_mes_morder.GetListAsync(x => string.IsNullOrEmpty(x.morder_state) == false && x.morder_state != "完成" && x.company_id == companyId && string.IsNullOrEmpty(x.analogcalcversion) && x.factory_id == factoryId && workordmsters.Select(c => c.WorkOrd).Contains(x.morder_no)).Result;
  6185. if (mes_morder.Count > 0)
  6186. {
  6187. mes_morder.ForEach(item => { item.bang_id = bangid; });
  6188. var moMes_morder = ObjectMapper.Map<List<mes_morder>, List<mo_mes_morder>>(mes_morder);
  6189. moMes_morder.ForEach(item => { item.GenerateNewId(help.NextId()); });
  6190. await MongoHelper<mo_mes_morder>.InsertManyAsync(moMes_morder);
  6191. }
  6192. //工单子表
  6193. var mes_moentry = _mysql_mes_moentry.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId).Result;
  6194. if (mes_moentry.Count > 0)
  6195. {
  6196. mes_moentry.ForEach(item => { item.bang_id = bangid; });
  6197. var moMes_moentry = ObjectMapper.Map<List<mes_moentry>, List<mo_mes_moentry>>(mes_moentry);
  6198. moMes_moentry.ForEach(item => { item.GenerateNewId(help.NextId()); });
  6199. await MongoHelper<mo_mes_moentry>.InsertManyAsync(moMes_moentry);
  6200. }
  6201. //在制工单占用记录表
  6202. var mes_mooccupy = _mysql_mes_mooccupy.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && mes_morder.Select(c => c.morder_no).Contains(x.moo_mo)).Result;
  6203. if (mes_mooccupy.Count > 0)
  6204. {
  6205. var moMes_mooccupy = ObjectMapper.Map<List<mes_mooccupy>, List<mo_mes_mooccupy>>(mes_mooccupy);
  6206. moMes_mooccupy.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; });
  6207. await MongoHelper<mo_mes_mooccupy>.InsertManyAsync(moMes_mooccupy);
  6208. }
  6209. }
  6210. //根据物料信息,只同步在途未关闭的采购订单和采购申请
  6211. //采购订单明细
  6212. var srm_po_list = _mysql_srm_po_list.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && itemIds.Contains(x.icitem_id.GetValueOrDefault())).Result;
  6213. if (srm_po_list.Count > 0)
  6214. {
  6215. //采购订单--取出状态为在途的PO
  6216. var srm_po_main = _mysql_srm_po_main.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && srm_po_list.Select(c => c.po_id).Contains(x.Id) && x.state != 3).Result;
  6217. if (srm_po_main.Count > 0)
  6218. {
  6219. var moSrm_po_main = ObjectMapper.Map<List<srm_po_main>, List<mo_srm_po_main>>(srm_po_main);
  6220. moSrm_po_main.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; });
  6221. await MongoHelper<mo_srm_po_main>.InsertManyAsync(moSrm_po_main);
  6222. //订单明细--根据在途PO过滤出有效的Po_list
  6223. srm_po_list = srm_po_list.Where(s => srm_po_main.Select(x => x.Id).Contains(s.po_id.GetValueOrDefault())).ToList();
  6224. var moSrm_po_list = ObjectMapper.Map<List<srm_po_list>, List<mo_srm_po_list>>(srm_po_list);
  6225. moSrm_po_list.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; item.create_time = DateTime.Now; });
  6226. await MongoHelper<mo_srm_po_list>.InsertManyAsync(moSrm_po_list);
  6227. }
  6228. //采购订单明细占用详情
  6229. var srm_po_occupy = _mysql_srm_po_occupy.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && srm_po_list.Select(c => c.Id).Contains(x.polist_id.GetValueOrDefault())).Result;
  6230. if (srm_po_occupy.Count > 0)
  6231. {
  6232. var moSrm_po_occupy = ObjectMapper.Map<List<srm_po_occupy>, List<mo_srm_po_occupy>>(srm_po_occupy);
  6233. moSrm_po_occupy.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; item.create_time = DateTime.Now; });
  6234. await MongoHelper<mo_srm_po_occupy>.InsertManyAsync(moSrm_po_occupy);
  6235. }
  6236. }
  6237. //pr
  6238. var srm_pr_main = new List<srm_pr_main>();
  6239. if (string.IsNullOrEmpty(analogCalcVersion))
  6240. {
  6241. //周计划屏蔽年度产生的PR
  6242. srm_pr_main = _mysql_srm_pr_main.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && x.state != 0 && string.IsNullOrEmpty(x.analogcalcversion) && itemIds.Contains(x.icitem_id.GetValueOrDefault())).Result;
  6243. }
  6244. else
  6245. {
  6246. srm_pr_main = _mysql_srm_pr_main.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && x.state != 0 && itemIds.Contains(x.icitem_id.GetValueOrDefault())).Result;
  6247. }
  6248. if (srm_pr_main.Count > 0)
  6249. {
  6250. var moSrm_pr_main = ObjectMapper.Map<List<srm_pr_main>, List<mo_srm_pr_main>>(srm_pr_main);
  6251. moSrm_pr_main.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; item.create_time = DateTime.Now; });
  6252. await MongoHelper<mo_srm_pr_main>.InsertManyAsync(moSrm_pr_main);
  6253. List<srm_po_occupy> occupylist = new List<srm_po_occupy>();
  6254. if (string.IsNullOrEmpty(analogCalcVersion))
  6255. {
  6256. var occupyListLINQ = _businessDbContext.srm_po_occupy.Where(x => x.company_id == companyId && x.factory_id == factoryId && !x.IsDeleted).Join(_businessDbContext.srm_pr_main.Where(x => x.company_id == companyId && x.factory_id == factoryId && x.state != 0 && string.IsNullOrEmpty(x.analogcalcversion) && itemIds.Contains(x.icitem_id.GetValueOrDefault())), p => p.polist_id, pr => pr.Id, (p, pr) => new { p, pr }).ToList();
  6257. for (int i = 0; i < occupyListLINQ.Count; i++)
  6258. {
  6259. occupylist.Add(occupyListLINQ[i].p);
  6260. }
  6261. }
  6262. else
  6263. {
  6264. var occupyListLINQ = _businessDbContext.srm_po_occupy.Where(x => x.company_id == companyId && x.factory_id == factoryId && !x.IsDeleted).Join(_businessDbContext.srm_pr_main.Where(x => x.company_id == companyId && x.factory_id == factoryId && x.state != 0 && itemIds.Contains(x.icitem_id.GetValueOrDefault())), p => p.polist_id, pr => pr.Id, (p, pr) => new { p, pr }).ToList();
  6265. for (int i = 0; i < occupyListLINQ.Count; i++)
  6266. {
  6267. occupylist.Add(occupyListLINQ[i].p);
  6268. }
  6269. }
  6270. //采购申请占用详情
  6271. //var srm_pr_occupy = _mysql_srm_po_occupy.GetListAsync(x => x.company_id == companyId && x.factory_id == factoryId && srm_pr_main.Select(c => c.Id).Contains(x.polist_id.GetValueOrDefault())).Result;
  6272. if (occupylist.Count > 0)
  6273. {
  6274. var moSrm_pr_occupy = ObjectMapper.Map<List<srm_po_occupy>, List<mo_srm_po_occupy>>(occupylist);
  6275. moSrm_pr_occupy.ForEach(item => { item.GenerateNewId(help.NextId()); item.bang_id = bangid; item.create_time = DateTime.Now; });
  6276. await MongoHelper<mo_srm_po_occupy>.InsertManyAsync(moSrm_pr_occupy);
  6277. }
  6278. }
  6279. var sysSet = _generalizedCodeMaster.Select(s => s.FldName == "SystemConfig" && s.Val == "ScheduleAgreement" && s.Domain == factoryId.ToString()).ToList();
  6280. int ScheduleAgreement = 0;//计划协议
  6281. if (sysSet.Any())
  6282. {
  6283. if (!string.IsNullOrEmpty(sysSet[0].Ufld1))
  6284. {
  6285. int.TryParse(sysSet[0].Ufld1, out ScheduleAgreement);
  6286. }
  6287. }
  6288. _CalcBomViewAppService.ScheduleAgreement = ScheduleAgreement == 1;
  6289. }
  6290. /// <summary>
  6291. /// 清处数据库快照
  6292. /// </summary>
  6293. /// <returns></returns>
  6294. public async Task ClearSnapShot(long bangid)
  6295. {
  6296. //清除物料库存数据
  6297. await MongoHelper<mo_ic_item_stock>.DeleteManyAsync(p => p.bang_id == bangid);
  6298. //清除工单占用记录表
  6299. //await _mes_mooccupy.DeleteAsync(p => p.bang_id == bangid);
  6300. //清除工单主表
  6301. //await _mes_morder.Delete(p => p.bang_id == bangid);
  6302. //清除工单子表
  6303. //await _mes_moentry.Delete(p => p.bang_id == bangid);
  6304. //清除采购订单
  6305. await MongoHelper<mo_srm_po_main>.DeleteManyAsync(p => p.bang_id == bangid);
  6306. //清除采购订单明细
  6307. await MongoHelper<mo_srm_po_list>.DeleteManyAsync(p => p.bang_id == bangid);
  6308. //清除采购订单占用详情
  6309. //await _srm_po_occupy.DeleteAsync(p => p.bang_id == bangid);
  6310. //清除PR
  6311. await MongoHelper<mo_srm_pr_main>.DeleteManyAsync(p => p.bang_id == bangid);
  6312. }
  6313. /// <summary>
  6314. /// 物料数据计算前准备
  6315. /// </summary>
  6316. /// <param name="boms"></param>
  6317. /// <param name="bangid"></param>
  6318. /// <param name="sorder"></param>
  6319. /// <param name="bomlist"></param>
  6320. /// <param name="bomchildlist"></param>
  6321. /// <param name="icitemlist"></param>
  6322. /// <param name="sublist"></param>
  6323. /// <param name="suballlist"></param>
  6324. /// <param name="subdtllist"></param>
  6325. /// <param name="stocklist"></param>
  6326. /// <param name="sklist"></param>
  6327. /// <exception cref="NotImplementedException"></exception>
  6328. public void DataInitialization(List<mo_ic_bom> boms, long bangid, List<mo_ic_item> icitemlist, List<mo_ic_item_stock> stocklist, List<b_bom_pretreatment> pretreatments, List<mo_ic_item_stockoccupy> sklist)
  6329. {
  6330. List<long> itemIds = pretreatments.Select(p => p.item_id.GetValueOrDefault()).Distinct().ToList();
  6331. icitemlist.AddRange(_ic_item.GetListAsync(p => itemIds.Contains(p.mysql_id) && !p.IsDeleted).Result);
  6332. #region 1、数据准备
  6333. //1.1、获取产能检查相关数据
  6334. //产品物料编码
  6335. List<string> itemnums = pretreatments.Where(p => p.level == 1).Select(p => p.item_number).Distinct().ToList();
  6336. //产线明细
  6337. prodLines = _prodLineDetail.Select(p => itemnums.Contains(p.Part)).ToList();
  6338. //标准工序
  6339. routingOps = _routingOpDetail.Select(p => p.Domain == param.factoryId.ToString()).ToList();
  6340. List<string> lines = prodLines.Select(p => p.Line).Distinct().ToList();
  6341. //工作日历
  6342. calendarWorks = _shopCalendarWorkCtr.Select(p => lines.Contains(p.ProdLine)).ToList();
  6343. //休息日
  6344. qualityLineWorks = _qualityLineWorkDetail.Select(p => lines.Contains(p.ProdLine)).ToList();
  6345. //节假日
  6346. holidays = _holidayMaster.Select(p => p.Dated >= DateTime.Now.Date);
  6347. //主工单
  6348. var ordlist = _workOrdMaster.Select(x => x.Domain == param.factoryId.ToString() && string.IsNullOrEmpty(x.Typed) == true && !string.IsNullOrEmpty(x.Status) && x.Status.ToUpper() != "C" && x.Status.ToUpper() != "P").ToList();
  6349. List<mo_mes_morder> mo_Mes_Morders = _mes_morder.GetListAsync(x => ordlist.Select(c => c.WorkOrd).Contains(x.morder_no) && x.company_id == param.company_id && x.factory_id == param.factoryId && x.bang_id == bangid).Result;
  6350. List<long> moids = mo_Mes_Morders.Select(p => p.mysql_id).ToList();
  6351. List<mo_mes_moentry> mo_Mes_Moentry = _mes_moentry.GetListAsync(x => moids.Contains(x.moentry_moid)).Result;
  6352. //工单占用表
  6353. List<mo_mes_mooccupy> mes_mooccupyList = _mes_mooccupy.GetListAsync(x => x.moo_state == 1 && !x.IsDeleted && x.company_id == param.company_id
  6354. && boms.Select(p => p.item_number).Contains(x.fitem_number) && x.bang_id == bangid).Result;
  6355. List<long> occoupyRefId = new List<long>();
  6356. //物料采购订单明细
  6357. var poDetailList = _srm_po_list.GetListAsync(x => icitemlist.Select(p => p.mysql_id).ToList().Contains(x.icitem_id.Value) && x.bang_id == bangid && x.state == 1 && !x.IsDeleted).Result;
  6358. occoupyRefId.AddRange(poDetailList.Select(p => p.mysql_id).ToList());
  6359. var srm_pr_mains = _srm_pr_main.GetListAsync(x => icitemlist.Select(p => p.mysql_id).ToList().Contains(x.icitem_id.Value) && x.bang_id == bangid && x.state != 0 && x.state != 4 && !x.IsDeleted).Result;
  6360. occoupyRefId.AddRange(srm_pr_mains.Select(p => p.mysql_id).ToList());
  6361. //采购订单或采购申请占用数据
  6362. var poOccupys = _srm_po_occupy.GetListAsync(x => occoupyRefId.Contains(x.polist_id) && x.bang_id == bangid && !x.IsDeleted).Result;
  6363. #endregion
  6364. //物料库存
  6365. stocklist.AddRange(_ic_item_stock.GetListAsync(p => p.factory_id == param.factoryId && p.bang_id == bangid && itemIds.Contains(p.icitem_id)).Result);
  6366. //物料库存占用表
  6367. sklist.AddRange(_ic_item_stockoccupy.GetListAsync(x => x.bang_id == bangid && !x.IsDeleted).Result);
  6368. //物料提前期
  6369. leadTimeList = GetLeadTime(icitemlist, param.company_id, param.factoryId);//提前期列表
  6370. supplierList = GetSupplier(itemIds, param.company_id, param.factoryId);//供应商列表
  6371. _CalcBomViewAppService.leadTimeList = leadTimeList;
  6372. _CalcBomViewAppService.supplierList = supplierList;
  6373. //资源检查添加产线工序等数据
  6374. _CalcBomViewAppService.prodLines = prodLines;
  6375. _CalcBomViewAppService.routingOps = routingOps;
  6376. _CalcBomViewAppService.calendarWorks = calendarWorks;
  6377. _CalcBomViewAppService.qualityLineWorks = qualityLineWorks;
  6378. _CalcBomViewAppService.holidays = holidays;
  6379. _CalcBomViewAppService.mordersList = mo_Mes_Morders;//工单
  6380. _CalcBomViewAppService.moentriesList = mo_Mes_Moentry;//工单子表
  6381. _CalcBomViewAppService.mooccupyAllList = mes_mooccupyList;//工单占用表
  6382. _CalcBomViewAppService.srm_Po_Lists = poDetailList; //采购明细
  6383. _CalcBomViewAppService.srm_Po_Occupies = poOccupys; //采购占用表
  6384. _CalcBomViewAppService.ic_item_List = icitemlist; //物料表
  6385. _CalcBomViewAppService.srm_Pr_Mains = srm_pr_mains;//PR
  6386. }
  6387. public void GenerateSort(List<BomChildExamineDto> returnlist)
  6388. {
  6389. int level = returnlist.Max(s => s.level);
  6390. returnlist.ForEach(s =>
  6391. {
  6392. int num = level - s.level;
  6393. if (num > 0)
  6394. {
  6395. s.num_order = long.Parse((s.num_order * Math.Pow(1000, num)).ToString());
  6396. }
  6397. });
  6398. }
  6399. /// <summary>
  6400. /// 根据物料id获取物料4个提前期
  6401. /// </summary>
  6402. /// <param name="icItemIds">物料id</param>
  6403. /// <param name="tenantId">企业id</param>
  6404. /// <param name="factoryid">工厂id</param>
  6405. /// <returns></returns>
  6406. private List<ICItemLeadTimeDto> GetLeadTime(List<mo_ic_item> icItemIds, long? companyId, long factoryid)
  6407. {
  6408. return icItemIds.Where(p => p.factory_id == factoryid && p.company_id == companyId && !p.IsDeleted).
  6409. Select(x => new ICItemLeadTimeDto
  6410. {
  6411. item_id = x.mysql_id,
  6412. transportation_leadtime = x.transportation_leadtime,
  6413. stock_leadtime = x.stock_leadtime,
  6414. production_leadtime = x.production_leadtime,
  6415. order_leadtime = x.order_leadtime,
  6416. minorderqty = x.minorderqty,
  6417. put_integer = x.put_integer,
  6418. minpackqty = x.minpackqty,
  6419. ordissu_days = x.ordissu_days
  6420. }).AsQueryable<ICItemLeadTimeDto>().ToList();
  6421. }
  6422. //根据物料id获取物料供应商
  6423. private List<mo_srm_purchase> GetSupplier(List<long> icItemIds, long? companyId, long factoryid)
  6424. {
  6425. return _srm_purchase.GetListAsync(p => icItemIds.Contains(p.icitem_id) && p.company_id == companyId && p.factory_id == factoryid && !p.IsDeleted).Result;
  6426. }
  6427. /// <summary>
  6428. /// 物料和BOM前置数据准备
  6429. /// </summary>
  6430. /// <param name="boms"></param>
  6431. /// <param name="bomlist"></param>
  6432. /// <param name="bomchildlist"></param>
  6433. /// <param name="icitemlist"></param>
  6434. /// <param name="sublist"></param>
  6435. /// <param name="suballlist"></param>
  6436. /// <param name="subdtllist"></param>
  6437. public void IcItemPretreatment(bool flag, List<mo_ic_bom> boms, List<mo_ic_bom> bomlist, List<mo_ic_bom_child> bomchildlist, List<mo_ic_item> icitemlist, List<mo_ic_substitute> sublist, List<mo_ic_substitute_group> suballlist, List<mo_ic_substitute_group_detail> subdtllist)
  6438. {
  6439. //获取物料bom,物料bom明细
  6440. GetIcBomData(boms, bomlist, bomchildlist, flag);
  6441. //根据明细集合查出所有得替代关系表数据集合
  6442. List<string> codeList = bomchildlist.Select(c => c.substitute_code).Distinct().ToList();
  6443. sublist.AddRange(_ic_substitute.GetListAsync(p => codeList.Contains(p.substitute_code) && !p.IsDeleted).Result);
  6444. List<long> subidlist = sublist.Select(c => c.mysql_id).Distinct().ToList();
  6445. suballlist.AddRange(_ic_substitute_group.GetListAsync(p => subidlist.Contains(p.substitute_group_id) && !p.IsDeleted).Result);
  6446. List<long> suballidlist = suballlist.Select(c => c.mysql_id).Distinct().ToList();
  6447. subdtllist.AddRange(_ic_substitute_group_detail.GetListAsync(p => suballidlist.Contains(p.substitute_group_id) && !p.IsDeleted).Result);
  6448. //获取物料数据
  6449. List<long> itemIds = bomlist.Select(p => p.icitem_id).ToList();
  6450. itemIds.AddRange(bomchildlist.Select(p => p.icitem_id).ToList());
  6451. itemIds.AddRange(subdtllist.Select(p => p.icitem_id).ToList());
  6452. icitemlist.AddRange(_ic_item.GetListAsync(p => itemIds.Contains(p.mysql_id) && !p.IsDeleted).Result);
  6453. }
  6454. /// <summary>
  6455. /// 递归:获取icbom,icbomchild数据
  6456. /// </summary>
  6457. /// <param name="icBoms"></param>
  6458. /// <param name="bomlist"></param>
  6459. /// <param name="bomchildlist"></param>
  6460. public void GetIcBomData(List<mo_ic_bom> icBoms, List<mo_ic_bom> bomlist, List<mo_ic_bom_child> bomchildlist, bool flag)
  6461. {
  6462. if (icBoms.Count == 0)
  6463. {
  6464. return;
  6465. }
  6466. //添加物料bom数据
  6467. foreach (var ib in icBoms)
  6468. {
  6469. if (!bomlist.Exists(s => s.mysql_id == ib.mysql_id))
  6470. {
  6471. bomlist.Add(ib);
  6472. }
  6473. }
  6474. List<long> icBomIds = icBoms.Select(m => m.mysql_id).ToList();
  6475. int page = 1;
  6476. page = (int)Math.Ceiling(icBomIds.Count() / (decimal)1500);
  6477. List<mo_ic_bom_child> childList = new List<mo_ic_bom_child>();
  6478. for (int i = 0; i < page; i++)
  6479. {
  6480. var pageBomsIds = icBomIds.Skip(i * 1500).Take(1500).ToList();
  6481. childList.AddRange(_ic_bom_child.GetListAsync(p => pageBomsIds.Contains(p.bom_id) && p.company_id == param.company_id && !p.IsDeleted).Result);
  6482. }
  6483. //没有明细数据,终止
  6484. if (childList.Count == 0)
  6485. {
  6486. return;
  6487. }
  6488. foreach (var bchild in childList)
  6489. {
  6490. if (!bomchildlist.Exists(s => s.mysql_id == bchild.mysql_id))
  6491. {
  6492. bomchildlist.Add(bchild);
  6493. }
  6494. }
  6495. if (flag)
  6496. { return; }
  6497. //通过物料bom明细数据反查物料bom数据
  6498. var boms = _ic_bom.GetListAsync(p => childList.Select(m => m.icitem_id).ToList().Contains(p.icitem_id) && p.use_status == 1 && p.company_id == param.company_id && !p.IsDeleted).Result.ToList();
  6499. foreach (var chd in childList)
  6500. {
  6501. var curBoms = boms.Where(p => p.icitem_id == chd.icitem_id).ToList();
  6502. GetIcBomData(curBoms, bomlist, bomchildlist, flag);
  6503. }
  6504. }
  6505. /// <summary>
  6506. /// 自动生成BOM预处理清单
  6507. /// </summary>
  6508. public void AutoCreateBomBill(string companyid, List<mo_ic_bom> ic_Boms = null)
  6509. {
  6510. try
  6511. {
  6512. bool flag = false;
  6513. if (ic_Boms == null)
  6514. {
  6515. flag = true;
  6516. ic_Boms = _ic_bom.GetListAsync(p => p.company_id.ToString() == companyid && !p.IsDeleted).Result.ToList();
  6517. }
  6518. var pretreatment = _mysql_b_bom_pretreatment.GetListAsync(s => ic_Boms.Select(c => c.mysql_id).ToList().Contains(s.sourceid)).Result;
  6519. param.company_id = long.Parse(companyid);
  6520. //物料bom
  6521. List<mo_ic_bom> bomlist = new List<mo_ic_bom>();
  6522. List<mo_ic_bom_child> bomchildlist = new List<mo_ic_bom_child>();
  6523. //物料信息
  6524. List<mo_ic_item> icitemlist = new List<mo_ic_item>();
  6525. //替代关系
  6526. List<mo_ic_substitute> sublist = new List<mo_ic_substitute>();
  6527. List<mo_ic_substitute_group> suballlist = new List<mo_ic_substitute_group>();
  6528. List<mo_ic_substitute_group_detail> subdtllist = new List<mo_ic_substitute_group_detail>();
  6529. IcItemPretreatment(flag, ic_Boms, bomlist, bomchildlist, icitemlist, sublist, suballlist, subdtllist);
  6530. List<b_bom_pretreatment> deleteList = new List<b_bom_pretreatment>();
  6531. List<b_bom_pretreatment> addList = new List<b_bom_pretreatment>();
  6532. foreach (var bom in ic_Boms)
  6533. {
  6534. var pret = pretreatment.Where(s => s.sourceid == bom.mysql_id).ToList();
  6535. if (pret.Any())
  6536. {
  6537. //版本不同则重新生成
  6538. deleteList.AddRange(pret);
  6539. }
  6540. //bom层级组装
  6541. var getBomList = _pretreatmentAppService.BomPretreatment(bom.mysql_id, bomlist, bomchildlist, icitemlist);
  6542. //bom替代关系组装
  6543. _pretreatmentAppService.BomSubstitute(getBomList, bomlist, bomchildlist, icitemlist, sublist, suballlist, subdtllist);
  6544. //GenerateSort(getBomList);
  6545. var list = ObjectMapper.Map<List<BomChildExamineDto>, List<b_bom_pretreatment>>(getBomList);
  6546. list.ForEach(s =>
  6547. {
  6548. s.sourceid = bom.mysql_id;
  6549. s.company_id = bom.company_id;
  6550. s.tenant_id = bom.tenant_id;
  6551. s.factory_id = bom.factory_id;
  6552. });
  6553. addList.AddRange(list);
  6554. }
  6555. if (deleteList.Any())
  6556. {
  6557. _businessDbContext.BulkDelete(deleteList);
  6558. }
  6559. if (addList.Any())
  6560. {
  6561. _businessDbContext.AddRange(addList);
  6562. }
  6563. _businessDbContext.SaveChanges();
  6564. }
  6565. catch (Exception e)
  6566. {
  6567. new NLogHelper("ResourceExamineAppService").WriteLog("AutoCreateBomBill", "自动生成BOM预处理清单:" + e.Message, _currentTenant.Id.ToString());
  6568. }
  6569. }
  6570. /// <summary>
  6571. /// 生产长周期物料PR
  6572. /// </summary>
  6573. /// <param name="input">需要传入工厂编码</param>
  6574. /// <returns></returns>
  6575. public async Task<string> CalcLongPeriodItemPR(InputDto input)
  6576. {
  6577. //来自定时任务的请求
  6578. if (input.year == 0 && input.month == 0)
  6579. {
  6580. input.year = DateTime.Now.Year;
  6581. input.month = DateTime.Now.Month;
  6582. }
  6583. if (DateTime.Now.Month >= 10)
  6584. {
  6585. input.year = DateTime.Now.AddYears(1).Year;
  6586. input.month = DateTime.Now.Month;
  6587. }
  6588. var ropParam = GetROPParam(input.factory_id.ToString());
  6589. //获取滚动未来六个月数据
  6590. var monthlist = GetYearPlanMonth(input.year);
  6591. var productList = _replenishmentAnnualProduction.GetListAsync(a => monthlist.Contains(a.PlanMonth) && !a.IsDeleted && a.factory_id == input.factory_id).Result.OrderBy(s => s.PlanMonth).ThenBy(s => s.OrderNum).ToList();
  6592. var itemList = productList.Select(a => a.SAPItemNumber).Distinct().ToList();
  6593. var planList = _mysql_ic_item.GetListAsync(a => itemList.Contains(a.number) && a.factory_id == input.factory_id && !a.IsDeleted).Result.ToList();
  6594. var mesItem = _itemMaster.Select(a => itemList.Contains(a.ItemNum) && a.IsActive && a.Domain == input.factory_id.ToString());
  6595. var bomList = _mysql_ic_bom.GetListAsync(a => itemList.Contains(a.item_number) && !a.IsDeleted && a.factory_id == input.factory_id).Result;
  6596. var planItemList = planList.Select(a => a.number).Distinct().ToList();
  6597. var expectedList = itemList.Except(planItemList).ToList();
  6598. if (expectedList.Count > 0)
  6599. {
  6600. throw new NotImplementedException("年度销售预测物料" + string.Join(",", expectedList) + "在DOP物料表找不到!");
  6601. }
  6602. var mesItemList = mesItem.Select(a => a.ItemNum).Distinct().ToList();
  6603. var expectedMesList = itemList.Except(mesItemList).ToList();
  6604. if (expectedMesList.Count > 0)
  6605. {
  6606. throw new NotImplementedException("年度销售预测物料" + string.Join(",", expectedMesList) + "在MES物料表找不到!");
  6607. }
  6608. var bomItemList = bomList.Select(a => a.item_number).Distinct().ToList();
  6609. var expectedBOMList = itemList.Except(bomItemList).ToList();
  6610. if (expectedBOMList.Count > 0)
  6611. {
  6612. throw new NotImplementedException("年度销售预测物料" + string.Join(",", expectedBOMList) + "在BOM没有维护!");
  6613. }
  6614. List<mes_morder> moList = new List<mes_morder>();
  6615. List<mes_moentry> moentryList = new List<mes_moentry>();
  6616. var list = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "M5", productList.Count(), "", 1);
  6617. long bangid = help.NextId();
  6618. for (int i = 0; i < productList.Count(); i++)
  6619. {
  6620. if (productList[i].Qty <= 0)
  6621. continue;
  6622. var ic_item = mesItem.Find(x => x.ItemNum == productList[i].SAPItemNumber);
  6623. var bom = bomList.Find(a => a.item_number == productList[i].SAPItemNumber);
  6624. mes_morder mes_Morder = new mes_morder();
  6625. mes_Morder.GenerateNewId(help.NextId());
  6626. mes_Morder.morder_type = MorderEnum.JhMorder;
  6627. mes_Morder.work_order_type = MorderEnum.CgMorder;
  6628. mes_Morder.morder_state = "";
  6629. mes_Morder.morder_no = list[i].NbrResult.ToString();
  6630. mes_Morder.fms_number = "";
  6631. mes_Morder.bom_number = bom.bom_number;
  6632. mes_Morder.fmodel = ic_item.Descr1;
  6633. mes_Morder.urgent = 1;
  6634. mes_Morder.moentry_startup_status = 0;
  6635. mes_Morder.tenant_id = input.tenant_id;
  6636. mes_Morder.factory_id = input.factory_id;
  6637. mes_Morder.company_id = input.company_id;
  6638. mes_Morder.org_id = input.org_id;
  6639. mes_Morder.product_code = ic_item.ItemNum;
  6640. mes_Morder.product_name = ic_item.Descr;
  6641. mes_Morder.morder_date = DateTime.Now.Date.AddDays(1);
  6642. mes_Morder.moentry_sys_stime = Convert.ToDateTime(productList[i].PlanMonth + "-01");
  6643. mes_Morder.moentry_prd = null;
  6644. mes_Morder.moentry_prdname = null;
  6645. mes_Morder.moentry_wrkc = null;
  6646. mes_Morder.moentry_wrkcname = null;
  6647. mes_Morder.picking_qty = 0;
  6648. mes_Morder.unit = ic_item.UM;
  6649. mes_Morder.morder_production_number = productList[i].Qty;
  6650. mes_Morder.need_number = productList[i].Qty;
  6651. mes_Morder.remaining_number = 0;
  6652. mes_Morder.create_time = DateTime.Now;
  6653. //生成工单子表数据
  6654. mes_moentry mes_Moentry = new mes_moentry();
  6655. mes_Moentry.GenerateNewId(help.NextId());
  6656. mes_Moentry.moentry_moid = mes_Morder.Id;
  6657. mes_Moentry.moentry_mono = mes_Morder.morder_no;
  6658. mes_Moentry.unit = ic_item.UM;
  6659. mes_Moentry.morder_production_number = productList[i].Qty;
  6660. mes_Moentry.need_number = productList[i].Qty;
  6661. mes_Moentry.remaining_number = 0;
  6662. mes_Moentry.tenant_id = input.tenant_id;
  6663. mes_Moentry.factory_id = input.factory_id;
  6664. mes_Moentry.company_id = input.company_id;
  6665. mes_Moentry.org_id = input.org_id;
  6666. mes_Moentry.create_time = DateTime.Now;
  6667. moList.Add(mes_Morder);
  6668. moentryList.Add(mes_Moentry);
  6669. }
  6670. var safeItemQty = _itemMaster.Select(a => a.PurMfg == "L" && a.SafetyStk > 0 && a.IsActive);
  6671. if (safeItemQty.Count > 0)
  6672. {
  6673. var itemStock = CalcStock(safeItemQty.Select(m => m.ItemNum).Distinct().ToList(), input);
  6674. var safelist = _serialNumberAppService.GetBillNo(input.factory_id.ToString(), "M5", safeItemQty.Count, "", 1);
  6675. for (int i = 0; i < safeItemQty.Count; i++)
  6676. {
  6677. mes_morder mes_Morder = new mes_morder();
  6678. mes_Morder.GenerateNewId(help.NextId());
  6679. mes_Morder.morder_type = MorderEnum.JhMorder;
  6680. mes_Morder.work_order_type = MorderEnum.CgMorder;
  6681. mes_Morder.morder_state = "";
  6682. mes_Morder.morder_no = safelist[i].NbrResult.ToString();
  6683. mes_Morder.fms_number = "";
  6684. mes_Morder.bom_number = safeItemQty[i].ItemNum;
  6685. mes_Morder.fmodel = safeItemQty[i].Descr1;
  6686. mes_Morder.urgent = 1;
  6687. mes_Morder.moentry_startup_status = 0;
  6688. mes_Morder.tenant_id = input.tenant_id;
  6689. mes_Morder.factory_id = input.factory_id;
  6690. mes_Morder.company_id = input.company_id;
  6691. mes_Morder.org_id = input.org_id;
  6692. mes_Morder.product_code = safeItemQty[i].ItemNum;
  6693. mes_Morder.product_name = safeItemQty[i].Descr;
  6694. mes_Morder.morder_date = DateTime.Now.Date.AddDays(1);
  6695. mes_Morder.moentry_sys_stime = Convert.ToDateTime(DateTime.Now.AddYears(1).Year + "-01-01");
  6696. mes_Morder.moentry_prd = null;
  6697. mes_Morder.moentry_prdname = null;
  6698. mes_Morder.moentry_wrkc = null;
  6699. mes_Morder.moentry_wrkcname = null;
  6700. mes_Morder.picking_qty = 0;
  6701. mes_Morder.unit = safeItemQty[i].UM;
  6702. var itemStockQty = itemStock.Find(a => a.ItemNumber == safeItemQty[i].ItemNum);
  6703. if (itemStockQty != null)
  6704. {
  6705. if (itemStockQty.Qty < safeItemQty[i].SafetyStk)
  6706. {
  6707. mes_Morder.morder_production_number = safeItemQty[i].SafetyStk - itemStockQty.Qty;
  6708. mes_Morder.need_number = safeItemQty[i].SafetyStk - itemStockQty.Qty;
  6709. }
  6710. else
  6711. {
  6712. //超过安全库存不用考虑
  6713. continue;
  6714. }
  6715. }
  6716. else
  6717. {
  6718. mes_Morder.morder_production_number = safeItemQty[i].SafetyStk;
  6719. mes_Morder.need_number = safeItemQty[i].SafetyStk;
  6720. }
  6721. mes_Morder.remaining_number = 0;
  6722. mes_Morder.create_time = DateTime.Now;
  6723. //生成工单子表数据
  6724. mes_moentry mes_Moentry = new mes_moentry();
  6725. mes_Moentry.GenerateNewId(help.NextId());
  6726. mes_Moentry.moentry_moid = mes_Morder.Id;
  6727. mes_Moentry.moentry_mono = mes_Morder.morder_no;
  6728. mes_Moentry.unit = safeItemQty[i].UM;
  6729. mes_Moentry.morder_production_number = safeItemQty[i].SafetyStk;
  6730. mes_Moentry.need_number = safeItemQty[i].SafetyStk;
  6731. mes_Moentry.remaining_number = 0;
  6732. mes_Moentry.tenant_id = input.tenant_id;
  6733. mes_Moentry.factory_id = input.factory_id;
  6734. mes_Moentry.company_id = input.company_id;
  6735. mes_Moentry.org_id = input.org_id;
  6736. mes_Moentry.create_time = DateTime.Now;
  6737. moList.Add(mes_Morder);
  6738. moentryList.Add(mes_Moentry);
  6739. }
  6740. }
  6741. //长周期物料只产生PR不生成实际工单
  6742. //await _mysql_mes_morder.InsertManyAsync(moList);
  6743. //await _mysql_mes_moentry.InsertManyAsync(moentryList);
  6744. moList = moList.OrderBy(a => a.moentry_sys_stime).ToList();
  6745. await PlanOrderResourceCheck(moList, moentryList, bangid, $"V{DateTime.Now.ToString("yyyyMMddHHmm")}", false, false);
  6746. return "OK";
  6747. }
  6748. public ReplenishmentDto GetROPParam(string domain)
  6749. {
  6750. //select [Domain],Val,Ufld1,UDeci1 from GeneralizedCodeMaster where [Domain] = '1001' AND FldName ='SystemConfig'
  6751. // AND Val IN('ReplenishmentCalcPeriod', 'HistoryOutStockMonth', 'SaleFcstMonth', 'SaleFcstEntryDate', 'UpdateWeeks', 'WeekPlanUpdateDay', 'LongPeriodDay')
  6752. List<string> list = new List<string>();
  6753. list.Add("ReplenishmentCalcPeriod");
  6754. list.Add("HistoryOutStockMonth");
  6755. list.Add("SaleFcstMonth");
  6756. list.Add("SaleFcstEntryDate");
  6757. list.Add("UpdateWeeks");
  6758. list.Add("WeekPlanUpdateDay");
  6759. list.Add("LongPeriodDay");
  6760. list.Add("IsUseROP");
  6761. var configList = _generalizedCodeMaster.Select(a => a.Domain == domain && a.FldName == "SystemConfig" && list.Contains(a.Val));
  6762. ReplenishmentDto replenishmentDto = new ReplenishmentDto();
  6763. replenishmentDto.HistoryOutStockMonth = 3;
  6764. replenishmentDto.ReplenishmentCalcPeriod = "W";
  6765. replenishmentDto.HistoryOutStockMonth = 2;
  6766. replenishmentDto.SaleFcstMonth = 2;
  6767. replenishmentDto.SaleFcstEntryDate = 27;
  6768. replenishmentDto.UpdateWeeks = 12;
  6769. replenishmentDto.WeekPlanUpdateDay = 7;//每周日更新
  6770. replenishmentDto.LongPeriodDay = 60;
  6771. replenishmentDto.IsUseROP = "否";
  6772. if (configList?.Find(a => a.Val == "HistoryOutStockMonth") != null)
  6773. {
  6774. replenishmentDto.HistoryOutStockMonth = (int)configList?.Find(a => a.Val == "HistoryOutStockMonth").UDeci1;
  6775. }
  6776. if (configList?.Find(a => a.Val == "ReplenishmentCalcPeriod") != null)
  6777. {
  6778. switch (configList?.Find(a => a.Val == "ReplenishmentCalcPeriod").Ufld1)
  6779. {
  6780. case "月":
  6781. replenishmentDto.ReplenishmentCalcPeriod = "M";
  6782. break;
  6783. case "周":
  6784. replenishmentDto.ReplenishmentCalcPeriod = "W";
  6785. break;
  6786. case "":
  6787. replenishmentDto.ReplenishmentCalcPeriod = "D";
  6788. break;
  6789. default:
  6790. replenishmentDto.ReplenishmentCalcPeriod = "W";
  6791. break;
  6792. }
  6793. }
  6794. if (configList?.Find(a => a.Val == "SaleFcstMonth") != null)
  6795. {
  6796. replenishmentDto.SaleFcstMonth = (int)configList?.Find(a => a.Val == "SaleFcstMonth").UDeci1;
  6797. }
  6798. if (configList?.Find(a => a.Val == "SaleFcstEntryDate") != null)
  6799. {
  6800. replenishmentDto.SaleFcstEntryDate = (int)configList?.Find(a => a.Val == "SaleFcstEntryDate").UDeci1;
  6801. }
  6802. if (configList?.Find(a => a.Val == "UpdateWeeks") != null)
  6803. {
  6804. replenishmentDto.UpdateWeeks = (int)configList?.Find(a => a.Val == "UpdateWeeks").UDeci1;
  6805. }
  6806. if (configList?.Find(a => a.Val == "WeekPlanUpdateDay") != null)
  6807. {
  6808. switch (configList?.Find(a => a.Val == "WeekPlanUpdateDay").Ufld1)
  6809. {
  6810. case "周一":
  6811. replenishmentDto.WeekPlanUpdateDay = 1;
  6812. break;
  6813. case "周二":
  6814. replenishmentDto.WeekPlanUpdateDay = 2;
  6815. break;
  6816. case "周三":
  6817. replenishmentDto.WeekPlanUpdateDay = 3;
  6818. break;
  6819. case "周四":
  6820. replenishmentDto.WeekPlanUpdateDay = 4;
  6821. break;
  6822. case "周五":
  6823. replenishmentDto.WeekPlanUpdateDay = 5;
  6824. break;
  6825. case "周六":
  6826. replenishmentDto.WeekPlanUpdateDay = 6;
  6827. break;
  6828. case "周日":
  6829. replenishmentDto.WeekPlanUpdateDay = 7;
  6830. break;
  6831. default:
  6832. replenishmentDto.WeekPlanUpdateDay = 7;
  6833. break;
  6834. }
  6835. }
  6836. if (configList?.Find(a => a.Val == "LongPeriodDay") != null)
  6837. {
  6838. replenishmentDto.LongPeriodDay = (int)configList?.Find(a => a.Val == "LongPeriodDay").UDeci1;
  6839. }
  6840. if (configList?.Find(a => a.Val == "IsUseROP") != null)
  6841. {
  6842. replenishmentDto.IsUseROP = configList?.Find(a => a.Val == "IsUseROP").Ufld1;
  6843. }
  6844. return replenishmentDto;
  6845. }
  6846. /// <summary>
  6847. /// 计算ABC分类和FMR分类
  6848. /// </summary>
  6849. /// <param name="replenishmentModels"></param>
  6850. public List<ReplenishmentROPWeekPlanDto> GetRopAmount(List<string> itemList, List<SupplierStatementDto> supplierStatementDtos, List<InvTransHist> invTransHists, InputDto input)
  6851. {
  6852. List<ReplenishmentROPWeekPlanDto> replenishmentROPWeekPlanDtos = new List<ReplenishmentROPWeekPlanDto>();
  6853. var total_outstock_amout = 0m;
  6854. foreach (var item in itemList)
  6855. {
  6856. var entry = supplierStatementDtos.FirstOrDefault(p => p.ItemNum == item);
  6857. decimal NETPR = 0m;
  6858. if (entry != null)
  6859. {
  6860. NETPR = entry.NETPR;
  6861. }
  6862. else
  6863. {
  6864. NETPR = 1;
  6865. }
  6866. //出库总数
  6867. var OutStockQty = invTransHists.Where(a => a.ItemNum == item).Sum(b => b.QtyChange);
  6868. ReplenishmentROPWeekPlanDto replenishmentROPWeekPlanDto = new ReplenishmentROPWeekPlanDto();
  6869. //出库总金额
  6870. replenishmentROPWeekPlanDto.outstock_amout = Math.Abs(OutStockQty.GetValueOrDefault()) * NETPR;
  6871. replenishmentROPWeekPlanDto.number = item;
  6872. total_outstock_amout += Math.Abs(OutStockQty.GetValueOrDefault()) * NETPR;
  6873. replenishmentROPWeekPlanDtos.Add(replenishmentROPWeekPlanDto);
  6874. }
  6875. replenishmentROPWeekPlanDtos = replenishmentROPWeekPlanDtos.OrderByDescending(a => a.outstock_amout).ToList();
  6876. var scale = 0m;
  6877. if (total_outstock_amout <= 0)
  6878. {
  6879. return null;
  6880. }
  6881. replenishmentROPWeekPlanDtos.ForEach(a =>
  6882. {
  6883. a.amout_scale = Math.Ceiling((a.outstock_amout / total_outstock_amout) * 100);
  6884. scale += a.amout_scale;
  6885. if (scale <= 80)
  6886. {
  6887. a.ABC = "A";
  6888. }
  6889. else if (scale >= 90)
  6890. {
  6891. a.ABC = "C";
  6892. }
  6893. else
  6894. {
  6895. a.ABC = "B";
  6896. }
  6897. });
  6898. return replenishmentROPWeekPlanDtos;
  6899. }
  6900. /// <summary>
  6901. /// 计算ABC分类和FMR分类
  6902. /// </summary>
  6903. /// <param name="replenishmentModels"></param>
  6904. public void CalcFMRAndABC(ReplenishmentROPWeekPlan replenishmentModel, ReplenishmentDto replenishmentDto, List<ASNBOLShipperDetail> shipList, List<InvTransHist> pickbilllist, List<ReplenishmentROPWeekPlanDto> replenishmentROPWeekPlanDtos, InputDto input)
  6905. {
  6906. //总的移库次数
  6907. int totalCount = shipList.Count() + pickbilllist.Count();
  6908. var items = shipList.Select(s => s.ContainerItem).Distinct().ToList();
  6909. items.AddRange(pickbilllist.Select(s => s.ItemNum).Distinct().ToList());
  6910. items = items.Distinct().ToList();
  6911. //平均出库次数
  6912. decimal avgOutStock = totalCount / replenishmentDto.HistoryOutStockMonth / items.Count();
  6913. //瑞奇不提供价格敏感信息,ABC类都默认为B,全部当做无出库金额的物料
  6914. //无出库金额的物料 FMR分类 F 96 % M 90 % R 80 %
  6915. //有出库金额的物料 ABC/ FMR分类 AF 96 % AM 90 % AR 80 % BF 96 % BM 90 % BR 80 % CF 96 % CM 90 % CR 80 %
  6916. if (replenishmentROPWeekPlanDtos.Any())
  6917. {
  6918. var abclist = replenishmentROPWeekPlanDtos.Where(a => a.number == replenishmentModel.number).ToList();
  6919. if (abclist.Any())
  6920. {
  6921. replenishmentModel.abc = abclist[0].ABC;
  6922. }
  6923. else
  6924. {
  6925. replenishmentModel.abc = "B";
  6926. }
  6927. }
  6928. else
  6929. {
  6930. //原材料默认为B
  6931. replenishmentModel.abc = "B";
  6932. }
  6933. int itemMoveCount = shipList.Count(a => a.ContainerItem == replenishmentModel.number) + pickbilllist.Count(a => a.ItemNum == replenishmentModel.number);
  6934. if (itemMoveCount > avgOutStock)
  6935. {
  6936. replenishmentModel.fmr = "F";
  6937. }
  6938. else if (itemMoveCount >= avgOutStock / 2 && itemMoveCount <= avgOutStock || itemMoveCount == 0)
  6939. {
  6940. replenishmentModel.fmr = "M";//没有出库移库记录的默认为M
  6941. }
  6942. else if (itemMoveCount < avgOutStock / 2)
  6943. {
  6944. replenishmentModel.fmr = "R";
  6945. }
  6946. if (replenishmentModel.fmr == "F")
  6947. {
  6948. replenishmentModel.service_level_pct = (decimal?)0.96;
  6949. }
  6950. if (replenishmentModel.fmr == "M")
  6951. {
  6952. replenishmentModel.service_level_pct = (decimal?)0.9;
  6953. }
  6954. if (replenishmentModel.fmr == "R")
  6955. {
  6956. replenishmentModel.service_level_pct = (decimal?)0.8;
  6957. }
  6958. }
  6959. /// <summary>
  6960. /// 算平均月需求数量
  6961. /// </summary>
  6962. /// <param name="planList">发货计划</param>
  6963. /// <param name="itemGroup"></param>
  6964. /// <param name="itemNum"></param>
  6965. /// <param name="month"></param>
  6966. /// <returns></returns>
  6967. public decimal CalcAvgDemand(List<MonthlyShipmentPlan> list, string itemNum, int? erp_cls, List<InvTransHist> pickbilllist = null)
  6968. {
  6969. if (erp_cls != 3)
  6970. {
  6971. if (list.Where(i => i.SAPItemNumber == itemNum && i.DistributionChannel == "瑞奇").Count() > 0)
  6972. {
  6973. return list.Where(i => i.SAPItemNumber == itemNum && i.DistributionChannel == "瑞奇").Average(a => a.Qty);
  6974. }
  6975. return 0;
  6976. }
  6977. else
  6978. {
  6979. var pickItemList = pickbilllist.Select(a => a.ItemNum).Distinct();
  6980. var sumQty = pickbilllist.Where(a => a.ItemNum == itemNum)?.Sum(a => a.QtyChange);
  6981. var month = pickbilllist.Where(a => a.ItemNum == itemNum)?.Select(a => a.CreateTime.Value.Month).Distinct().Count();
  6982. if (month == 0)
  6983. return sumQty.Value;
  6984. else
  6985. return sumQty.GetValueOrDefault() / month.Value;
  6986. }
  6987. }
  6988. public double CalcVariance(List<MonthlyShipmentPlan> list, string itemNum, int? erp_cls, decimal? monthl_avg_demand, List<InvTransHist> pickbilllist = null)
  6989. {
  6990. if (erp_cls != 3)
  6991. {
  6992. var nums = list.Where(i => i.SAPItemNumber == itemNum).Select(a => a.Qty);
  6993. if (nums.Count() <= 1)
  6994. return 0;
  6995. return Math.Sqrt(nums.Sum(x => Math.Pow(Convert.ToDouble(x) - Convert.ToDouble(monthl_avg_demand), 2)) / (nums.Count() - 1));
  6996. }
  6997. else
  6998. {
  6999. var nums = pickbilllist.Where(i => i.ItemNum == itemNum).Select(a => a.QtyChange);
  7000. if (nums.Count() <= 1)
  7001. return 0;
  7002. return Math.Sqrt(nums.Sum(x => Math.Pow(Convert.ToDouble(x) - Convert.ToDouble(monthl_avg_demand), 2)) / (nums.Count() - 1));
  7003. }
  7004. }
  7005. /// <summary>
  7006. /// 获取指定日期在为一年中为第几周
  7007. /// </summary>
  7008. /// <param name="dt">指定时间</param>
  7009. /// <reutrn>返回第几周</reutrn>
  7010. public static int GetWeekOfYear(DateTime dt)
  7011. {
  7012. System.Globalization.GregorianCalendar gc = new System.Globalization.GregorianCalendar();
  7013. int weekOfYear = gc.GetWeekOfYear(dt, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Monday);
  7014. return weekOfYear;
  7015. }
  7016. //获取上周开始时间
  7017. public static DateTime getPreWeekStartTime()
  7018. {
  7019. var weekday = (int)DateTime.Now.DayOfWeek;
  7020. return Convert.ToDateTime(DateTime.Now.AddDays(-7 - weekday + 1).ToString("yyyy-MM-dd 00:00:00.000"));
  7021. }
  7022. //获取上周结束时间
  7023. public static DateTime getPreWeekEndTime()
  7024. {
  7025. int weekday = (int)DateTime.Now.DayOfWeek;
  7026. return Convert.ToDateTime(DateTime.Now.AddDays(weekday - 7 + 1).ToString("yyyy-MM-dd 23:59:59.000"));
  7027. }
  7028. /// <summary>
  7029. /// 获取上个月开始时间
  7030. /// </summary>
  7031. /// <param name="months"></param>
  7032. /// <returns></returns>
  7033. public static DateTime getPreMonthStartTime()
  7034. {
  7035. return Convert.ToDateTime(DateTime.Now.AddMonths(-1).AddDays(1 - DateTime.Now.Day).ToString("yyyy-MM-dd 00:00:00.000"));
  7036. }
  7037. /// <summary>
  7038. /// 获取上月结束时间
  7039. /// </summary>
  7040. /// <param name="months"></param>
  7041. /// <returns></returns>
  7042. public static DateTime getPreMonthEndTime()
  7043. {
  7044. return Convert.ToDateTime(DateTime.Now.AddDays(-DateTime.Now.Day).ToString("yyyy-MM-dd 23:59:59.000"));
  7045. }
  7046. /// <summary>
  7047. /// 获取前后某个,整数月开始时间
  7048. /// </summary>
  7049. /// <param name="months">正数表示后多少个月的第一天,负数为前多少个月第一天</param>
  7050. /// <returns></returns>
  7051. public static DateTime getMonthStartTime(int months)
  7052. {
  7053. return getPreMonthStartTime().AddMonths(months + 1);
  7054. }
  7055. /// <summary>
  7056. /// 获取前后某个,整数月结束时间
  7057. /// </summary>
  7058. /// <param name="months">正数表示后多少个月的第一天,负数为前多少个月第一天</param>
  7059. /// <returns></returns>
  7060. public static DateTime getMonthEndTime(int months)
  7061. {
  7062. return getPreMonthEndTime().AddMonths(months + 1);
  7063. }
  7064. /// <summary>
  7065. /// 获取未来几个月PlanMonth
  7066. /// </summary>
  7067. /// <param name="monthCount"></param>
  7068. /// <returns></returns>
  7069. public List<string> GetPlanMonth(int monthCount)
  7070. {
  7071. List<string> result = new List<string>();
  7072. for (int i = 0; i < monthCount; i++)
  7073. {
  7074. var months = DateTime.Now.AddMonths(i);
  7075. result.Add($"{months.Year}-{months.Month.ToString("00")}");
  7076. }
  7077. return result;
  7078. }
  7079. public List<string> GetYearPlanMonth(int year)
  7080. {
  7081. List<string> result = new List<string>();
  7082. for (int i = 0; i < 12; i++)
  7083. {
  7084. var months = Convert.ToDateTime($"{year}-01-01");
  7085. months = months.AddMonths(i);
  7086. result.Add($"{months.Year}-{months.Month.ToString("00")}");
  7087. }
  7088. return result;
  7089. }
  7090. /// <summary>
  7091. /// 获取前面几个月PlanMonth
  7092. /// </summary>
  7093. /// <param name="monthCount"></param>
  7094. /// <returns></returns>
  7095. public List<string> GetPrePlanMonth(int monthCount)
  7096. {
  7097. List<string> result = new List<string>();
  7098. for (int i = 0; i < monthCount; i++)
  7099. {
  7100. var months = DateTime.Now.AddMonths(-i);
  7101. result.Add($"{months.Year}-{months.Month.ToString("00")}");
  7102. }
  7103. return result;
  7104. }
  7105. public async Task AsyncItemStockFromWMS(List<string> itemList, string analogCalcVersion)
  7106. {
  7107. //释放库存占用记录
  7108. await _systemJobAppService.SyncItemStockOccupyClear();
  7109. //产品编码
  7110. //var itemList = bom_Pretreatments.Select(a => a.item_number).Distinct().ToList();
  7111. List<string> itemChildList = new List<string>();
  7112. itemChildList.AddRange(itemList.Distinct());
  7113. if (!itemChildList.Any())
  7114. {
  7115. return;
  7116. }
  7117. //List<string> locationList = new List<string> { "1000", "1001", "5008", "8000", "8001" };
  7118. var locationRange = _configurationItem.Select(x => x.FldName == "MRPLocationRange" && x.Domain == param.factoryId.ToString()).FirstOrDefault();
  7119. List<string> locationList = new List<string> { "1000", "1001", "5008", "8000", "8001" };
  7120. if (locationRange != null && locationRange.Val != null)
  7121. {
  7122. locationList = locationRange.Val.SplitToArray(",").ToList();
  7123. }
  7124. if (!param.checkPlan)
  7125. {
  7126. if (locationList.Contains("1000"))
  7127. {
  7128. locationList.Remove("1000");
  7129. }
  7130. }
  7131. var locStock = _invMaster.Select(a => itemChildList.Contains(a.ItemNum) && a.IsActive && a.Domain == param.factoryId.ToString() && locationList.Contains(a.Location));
  7132. //var sapInvList = _SAPInv.Select(a => a.WERKS == param.factoryId.ToString() && itemChildList.Contains(a.MATNR) && (a.SOBKZ.ToUpper() == "O" || locationList.Contains(a.LGORT)));
  7133. //根据WMS物料,取出DOP物料数据
  7134. var items = _mysql_ic_item.GetListAsync(a => itemChildList.Contains(a.number) && a.factory_id == param.factoryId).Result;
  7135. var itemIds = items.Select(b => b.Id).ToList();//需要处理的dop物料id集合
  7136. List<ic_item_stock> mysqlStock = _mysql_ic_item_stock.GetListAsync(a => itemIds.Contains(a.icitem_id) && a.factory_id == param.factoryId).Result;
  7137. List<ic_item_stock> needAddList = new List<ic_item_stock>();
  7138. List<ic_item_stock> needupdList = new List<ic_item_stock>();
  7139. foreach (var stockWMS in itemChildList)
  7140. {
  7141. var num = items.Find(x => x.number == stockWMS);
  7142. if (num != null)
  7143. {
  7144. var item = mysqlStock.Find(a => a.icitem_id == num.Id);
  7145. if (item != null)
  7146. {
  7147. needupdList.Add(item);
  7148. }
  7149. else
  7150. {
  7151. item = new ic_item_stock();
  7152. item.GenerateNewId(help.NextId());
  7153. item.tenant_id = param.company_id;
  7154. item.factory_id = param.factoryId;
  7155. item.company_id = param.company_id;
  7156. item.icitem_id = num.Id;
  7157. item.icitem_number = num.number;
  7158. item.icitem_name = num.name;
  7159. needAddList.Add(item);
  7160. }
  7161. item.sqty = 0;
  7162. foreach (var lct in locationList)
  7163. {
  7164. var lctQty = locStock.Where(s => s.ItemNum == item.icitem_number && s.Location == lct).Sum(p => p.AvailStatusQty.GetValueOrDefault() + p.Assay.GetValueOrDefault());
  7165. //if (lctQty == 0)
  7166. //{
  7167. // lctQty = sapInvList.Where(x => x.MATNR == item.icitem_number && x.LGORT == lct).Sum(p => p.LABST + p.INSME);
  7168. //}
  7169. item.sqty += lctQty;
  7170. }
  7171. //if (!string.IsNullOrEmpty(analogCalcVersion))
  7172. //{
  7173. // item.sqty += sapInvList.Where(x => x.MATNR == item.icitem_number && x.SOBKZ.ToUpper() == "O").Sum(p => p.LABST + p.INSME);
  7174. //}
  7175. }
  7176. }
  7177. if (needAddList.Count > 0)
  7178. {
  7179. await _businessDbContext.AddRangeAsync(needAddList);
  7180. }
  7181. _businessDbContext.UpdateRange(needupdList);
  7182. await _businessBangDbContext.SaveChangesAsync();
  7183. }
  7184. public async Task<string> DeleteWeekPlan(long weekplanid, string productorder, long factory_id)
  7185. {
  7186. //2023/12/16 所有工单类型都能删除,中间件由业务人员自行处理
  7187. var weekplan = _replenishmentWeekPlan.GetListAsync(a => a.Id == weekplanid && a.ProductionOrder == productorder && a.factory_id == factory_id && a.IsReplenishmentModel == "N").Result;
  7188. var workords = _workOrdMaster.Select(a => a.RecID == weekplanid && a.WorkOrd == productorder && a.Domain == factory_id.ToString());
  7189. var morders = _mysql_mes_morder.GetListAsync(a => a.Id == weekplanid && a.morder_no == productorder && a.factory_id == factory_id).Result;
  7190. if (weekplan.Count == 0 && workords.Count == 0 && morders.Count == 0)
  7191. return "Fail|周计划或工单不存在";
  7192. if (string.IsNullOrEmpty(productorder))
  7193. {
  7194. //未同步生产周计划工单,只需要删除导入的周计划
  7195. await _replenishmentWeekPlan.HardDeleteAsync(a => a.Id == weekplanid && a.ProductionOrder == productorder && a.factory_id == factory_id && a.IsReplenishmentModel == "N");
  7196. return "OK|删除成功";
  7197. }
  7198. else
  7199. {
  7200. //判断是否下达
  7201. var workord = _workOrdMaster.Select(a => a.WorkOrd == productorder && a.Domain == factory_id.ToString());
  7202. if (workord.Count > 0)
  7203. {
  7204. //未下达的工单才可以删除,也就是初始或者已发布的工单
  7205. if (string.IsNullOrEmpty(workord[0].Status) || workord[0].Status.ToLower() == "p")
  7206. {
  7207. if (morders.Any())
  7208. {
  7209. //如果是订单类型执行的删除,则将订单表更新成删除。
  7210. var melist = _mysql_mes_moentry.GetListAsync(x => x.moentry_moid == weekplanid).Result;
  7211. var entry_id = melist.Select(x => x.soentry_id.GetValueOrDefault()).ToList();
  7212. List<crm_seorderentry> selist = _mysql_crm_seorderentry.GetListAsync(x => entry_id.Contains(x.Id)).Result;
  7213. await _mysql_crm_seorderentry.HardDeleteAsync(selist);
  7214. List<crm_seorder> solist = _mysql_crm_seorder.GetListAsync(x => selist.Select(c => c.seorder_id.GetValueOrDefault()).Contains(x.Id)).Result;
  7215. List<crm_seorderentry> allseList = _mysql_crm_seorderentry.GetListAsync(x => solist.Select(c => c.Id).Contains(x.seorder_id.GetValueOrDefault()) && !entry_id.Contains(x.Id)).Result;
  7216. List<crm_seorder> delsoList = new List<crm_seorder>();
  7217. foreach (var so in solist)
  7218. {
  7219. if (!allseList.Where(x => x.seorder_id == so.Id).Any())
  7220. {
  7221. delsoList.Add(so);
  7222. }
  7223. }
  7224. if (delsoList.Any())
  7225. {
  7226. await _mysql_crm_seorder.HardDeleteAsync(delsoList);
  7227. }
  7228. }
  7229. new NLogHelper("DeleteWeekPlan").WriteLog("DeleteWeekPlan", "删除工单:" + productorder + "__" + workord[0].Status, _currentTenant.Id.ToString());
  7230. await _replenishmentWeekPlan.HardDeleteAsync(a => a.ProductionOrder == productorder && a.factory_id == factory_id);
  7231. await _mysql_mes_morder.HardDeleteAsync(a => a.morder_no == productorder && a.factory_id == factory_id);
  7232. await _mysql_mes_moentry.HardDeleteAsync(a => a.moentry_mono == productorder && a.factory_id == factory_id);
  7233. _workOrdMaster.Delete(a => a.WorkOrd == productorder && a.Domain == factory_id.ToString());
  7234. _workOrdDetail.Delete(a => a.WorkOrd == productorder && a.Domain == factory_id.ToString());
  7235. _workOrdRouting.Delete(a => a.WorkOrd == productorder && a.Domain == factory_id.ToString());
  7236. _scheduleResultOpMaster.Delete(a => a.WorkOrd == productorder && a.Domain == factory_id.ToString());
  7237. _periodSequenceDet.Delete(a => a.WorkOrds == productorder && a.Domain == factory_id.ToString());
  7238. await _mysql_ic_item_stockoccupy.HardDeleteAsync(a => a.morder_mo == productorder && a.factory_id == factory_id);
  7239. await _mysql_srm_po_occupy.HardDeleteAsync(a => a.morder_mo == productorder && a.factory_id == factory_id);
  7240. await _mysql_mes_mooccupy.HardDeleteAsync(a => a.moo_mo == productorder && a.factory_id == factory_id);
  7241. return "OK|删除成功";
  7242. }
  7243. else
  7244. {
  7245. return "Fail|该工单非下达,请走工单关闭。";
  7246. }
  7247. }
  7248. else
  7249. {
  7250. return "Fail|工单不存在";
  7251. }
  7252. }
  7253. }
  7254. /// <summary>
  7255. /// 生成交货单
  7256. /// </summary>
  7257. /// <param name="domain"></param>
  7258. /// <param name="user"></param>
  7259. /// <returns></returns>
  7260. public async Task<string> CreateDeliverySchedule(string domain, string user)
  7261. {
  7262. string Msg = "OK|交货单生成成功";
  7263. //获取已发布且净需求数量大于0的交货计划数据
  7264. var demandplans = _icdemandschedule.GetListAsync(p => p.factory_id.ToString() == domain && p.status.ToUpper() == "P" && p.tosechedqty > 0 && !p.IsDeleted && string.IsNullOrEmpty(p.ishistoryversion)).Result.OrderBy(p => p.arrivaldate).ToList();
  7265. //获取已以生成交货单的交货计划
  7266. var alreadys = _srmpolistds.Select(p => p.domain == domain && demandplans.Select(m => m.Id).Contains(p.icdsid) && p.isactive == 1).ToList();
  7267. List<ic_demandschedule> newPlans = new List<ic_demandschedule>();
  7268. if (alreadys.Any())
  7269. {
  7270. //交货计划存在已发布或者已关闭状态的交货单
  7271. List<long> yfbIds = alreadys.Where(p => p.status.ToUpper() == "P" || p.status.ToUpper() == "C").Select(p => p.icdsid).Distinct().ToList();
  7272. //交货计划生成过交货单,但都是未发布状态
  7273. var wfbDs = alreadys.Where(p => !yfbIds.Contains(p.icdsid)).ToList();
  7274. if (wfbDs.Any())
  7275. {
  7276. wfbDs.ForEach(p => p.isactive = 0);
  7277. //删除未发布的交货单
  7278. _srmpolistds.Update(wfbDs);
  7279. }
  7280. //未发布交货单的交货计划
  7281. var wfbPlans = demandplans.Where(p => !yfbIds.Contains(p.Id)).ToList();
  7282. if (wfbPlans.Any())
  7283. {
  7284. newPlans.AddRange(wfbPlans);
  7285. }
  7286. //如果已生成交货单的数量小于交货计划的净需求数量,则需要重新生成交货单
  7287. var yfbJhds = alreadys.Where(p => yfbIds.Contains(p.icdsid)).ToList();
  7288. var yfbPlans = demandplans.Where(p => yfbIds.Contains(p.Id)).ToList();
  7289. //净需求数量
  7290. ic_demandschedule newInsert = new ic_demandschedule();
  7291. foreach (var item in yfbPlans)
  7292. {
  7293. var curJhds = yfbJhds.Where(p => p.icdsid == item.Id).ToList();
  7294. decimal sumQty = curJhds.Where(p => p.status.ToUpper() == "C").Sum(p => p.sentqty) + curJhds.Where(p => p.status.ToUpper() != "C").Sum(p => p.schedqty);
  7295. if (item.tosechedqty <= sumQty)
  7296. {
  7297. continue;
  7298. }
  7299. //tosechedqty = item.tosechedqty - sumQty;
  7300. newInsert = new ic_demandschedule();
  7301. newInsert.GenerateNewId(item.Id);
  7302. newInsert.itemnum = item.itemnum;
  7303. newInsert.tosechedqty = item.tosechedqty - sumQty;
  7304. newInsert.fversion = item.fversion;
  7305. newInsert.drawing = item.drawing;
  7306. newInsert.requestdate = item.requestdate;
  7307. newInsert.arrivaldate = item.arrivaldate;
  7308. newInsert.shortqty = item.shortqty;
  7309. newInsert.mesqty = item.mesqty;
  7310. newInsert.locqty = item.locqty;
  7311. newInsert.sechedqty = item.sechedqty;
  7312. newInsert.status = item.status;
  7313. newInsert.remarks = item.remarks;
  7314. newInsert.ishistoryversion = item.ishistoryversion;
  7315. newInsert.historyversionTime = item.historyversionTime;
  7316. newPlans.Add(newInsert);
  7317. }
  7318. demandplans = newPlans;
  7319. }
  7320. //根据交货计划物料编码,获取物料属性为采购件的物料主数据
  7321. List<ItemMaster> itemMasters = _itemMaster.Select(p => demandplans.Select(m => m.itemnum).Contains(p.ItemNum) && p.Domain == domain && (p.PurMfg == "P" || p.PurMfg == "p")).ToList();
  7322. if (!itemMasters.Any())
  7323. {
  7324. Msg = "OK|物料交货计划中没有采购件,不需要生成交货单";
  7325. return Msg;
  7326. }
  7327. //过滤掉物料属性不为采购件的交货计划
  7328. demandplans = demandplans.Where(p => itemMasters.Select(m => m.ItemNum).Contains(p.itemnum)).ToList();
  7329. if (!demandplans.Any())
  7330. {
  7331. Msg = "OK|物料交货计划中没有采购件,不需要生成交货单";
  7332. return Msg;
  7333. }
  7334. List<string> itemnums = demandplans.Select(p => p.itemnum).ToList();
  7335. //获取物料主数据
  7336. var icitems = _mysql_ic_item.GetListAsync(a => itemnums.Contains(a.number) && a.factory_id.ToString() == domain && !a.IsDeleted).Result.ToList();
  7337. //获取货源清单数据
  7338. var purchases = _srmPurchase.GetListAsync(p => p.factory_id.ToString() == domain && p.is_active == "否" && itemnums.Contains(p.number) && !p.IsDeleted).Result;
  7339. if (!purchases.Any())
  7340. {
  7341. Msg = "NO|没有可用的货源清单";
  7342. return Msg;
  7343. }
  7344. //获取采购明细数据:未关闭,且未交货数量(需求数量-已收数量)>0
  7345. List<PurOrdDetail> purOrdDetails = _PurOrdDetail.Select(p => p.Domain == domain && itemnums.Contains(p.ItemNum) && p.Status.ToUpper() != "C" && (p.QtyOrded - p.RctQty) > 0).OrderBy(p => p.DueDate).ToList();
  7346. List<string> purOrds = purOrdDetails.Select(p => p.PurOrd).Distinct().ToList();
  7347. //获取送货单子表数据
  7348. List<scm_shdzb> shdzbs = _scm_shdzb.Select(p => purOrds.Contains(p.po_bill) && itemnums.Contains(p.sh_material_code) && string.IsNullOrEmpty(p.jhdbh)).ToList();
  7349. //获取采购单数据
  7350. List<PurOrdMaster> purOrdMasters = _PurOrdMaster.Select(p => p.Domain == domain && purOrds.Contains(p.PurOrd)).ToList();
  7351. //获取占用可用PO明细的交货单
  7352. List<srm_polist_ds> dbPolistds = _srmpolistds.Select(p => purOrds.Contains(p.ponumber) && p.isactive == 1).ToList();
  7353. //获取已完成的送货单子表数据
  7354. var purOrdNos = purOrds.JoinAsString("','");
  7355. var itemnumNos = itemnums.JoinAsString("','");
  7356. string sql = $"select b.id,[po_billline],[jhdbh],isnull([shzt],'待收') shzt,[jhdhh] ,b.sh_material_code,b.sh_material_name,b.po_bill,b.sh_delivery_quantity,a.sh_purchase_num,b.id as sh_purchase_id,CONVERT(DATE,GETDATE(),23) jhshrq,CONVERT(DATE,GETDATE(),23) yjdhrq,b.id as polist_id " +
  7357. $"from scm_shd a left join scm_shdzb b on a.id=b.glid where po_bill in ('{purOrdNos}') and sh_material_code in ('{itemnumNos}') and jhdbh!='' and shzt='完成'";
  7358. var Endshdzbs = _businessDbContext.scm_shdzbDto.FromSqlRaw(sql).ToList();
  7359. //过滤PO、DO:
  7360. //1、PO只有采购组为110,160的采购订单能使用
  7361. //2、DO只有供应类别为"标准"或"VMI"的才能使用
  7362. List<PurOrdMaster> newPurMasters = new List<PurOrdMaster>();
  7363. var kyPoList = purOrdMasters.Where(p => !p.PurOrd.StartsWith("DO") && (p.Buyer == "110" || p.Buyer == "160" || p.Buyer == "170")).ToList();
  7364. if (kyPoList.Any())
  7365. {
  7366. newPurMasters.AddRange(kyPoList);
  7367. }
  7368. var kyDoList = purOrdMasters.Where(p => p.PurOrd.StartsWith("DO") && (p.USAGE == "标准" || p.USAGE == "VMI" || p.USAGE == "委外加工")).ToList();
  7369. if (kyDoList.Any())
  7370. {
  7371. newPurMasters.AddRange(kyDoList);
  7372. }
  7373. purOrdMasters = newPurMasters;
  7374. //过滤采购单明细
  7375. purOrdDetails = purOrdDetails.Where(p => purOrdMasters.Select(m => m.PurOrd).Contains(p.PurOrd)).ToList();
  7376. //获取系统级参数:是否启用计划协议(0不启用,1启用)
  7377. var sysSet = _generalizedCodeMaster.Select(s => s.FldName == "SystemConfig" && s.Val == "ScheduleAgreement" && s.Domain == param.factoryId.ToString()).ToList();
  7378. int ScheduleAgreement = 0;
  7379. if (sysSet.Any())
  7380. {
  7381. if (!string.IsNullOrEmpty(sysSet[0].Ufld1))
  7382. {
  7383. int.TryParse(sysSet[0].Ufld1, out ScheduleAgreement);
  7384. }
  7385. }
  7386. //生成交货单
  7387. srm_polist_ds entity;
  7388. List<srm_polist_ds> inserts = new List<srm_polist_ds>();
  7389. //新生成的PR
  7390. srm_pr_main srm_Pr = new srm_pr_main();
  7391. List<srm_pr_main> prInserts = new List<srm_pr_main>();
  7392. //交货单异常记录
  7393. List<DeliveryExceptionMaster> exceptions = new List<DeliveryExceptionMaster>();
  7394. DeliveryExceptionMaster info = new DeliveryExceptionMaster();
  7395. //操作时间
  7396. string optime = DateTime.Now.ToString("yyyyMMddHHmmss");
  7397. //采购明细剩余未交数量
  7398. decimal sumRestQty = 0m;
  7399. //交货单占用数量
  7400. decimal sumDbOccupy = 0m;
  7401. //本次计算占用数量
  7402. decimal sumCurOccupy = 0m;
  7403. //剩余可用数量
  7404. decimal restQty = 0m;
  7405. demandplans = demandplans.OrderBy(p => p.requestdate).ToList();
  7406. for (int i = 0; i < demandplans.Count; i++)
  7407. {
  7408. //物料数据
  7409. var curItem = icitems.FirstOrDefault(p => p.number == demandplans[i].itemnum);
  7410. if (curItem == null)
  7411. {
  7412. //添加异常记录
  7413. info = new DeliveryExceptionMaster();
  7414. info.Domain = domain;
  7415. info.Icdsid = demandplans[i].Id;
  7416. info.ItemNum = demandplans[i].itemnum;
  7417. info.CreateTime = DateTime.Now;
  7418. info.Remark = "物料交货计划[" + demandplans[i].itemnum + ":" + demandplans[i].requestdate.ToString("yyyy-MM-dd") + "]物料尚未同步到ic_item表,请同步后再生成交货单";
  7419. info.NeedQty = 0;
  7420. info.OptTime = optime;
  7421. exceptions.Add(info);
  7422. continue;
  7423. }
  7424. //获取当前交货计划物料对应的货源清单
  7425. var curChaes = purchases.Where(p => p.number == demandplans[i].itemnum).OrderByDescending(p => p.quota_rate).ToList();
  7426. //校验1:如果当前物料没有维护货源清单,则跳过
  7427. if (!curChaes.Any())
  7428. {
  7429. info = new DeliveryExceptionMaster();
  7430. info.Domain = domain;
  7431. info.Icdsid = demandplans[i].Id;
  7432. info.ItemNum = demandplans[i].itemnum;
  7433. info.CreateTime = DateTime.Now;
  7434. info.Remark = "物料交货计划[" + demandplans[i].itemnum + ":" + demandplans[i].requestdate.ToString("yyyy-MM-dd") + "]没有维护货源清单,无法转交货单";
  7435. info.OptTime = optime;
  7436. exceptions.Add(info);
  7437. continue;
  7438. }
  7439. //校验2:如果当前物料对应货源清单的供应商配额之和不为100%,则跳过
  7440. if (curChaes.Sum(p => p.quota_rate.GetValueOrDefault()) != 100)
  7441. {
  7442. info = new DeliveryExceptionMaster();
  7443. info.Domain = domain;
  7444. info.Icdsid = demandplans[i].Id;
  7445. info.ItemNum = demandplans[i].itemnum;
  7446. info.CreateTime = DateTime.Now;
  7447. info.Remark = "物料交货计划[" + demandplans[i].itemnum + ":" + demandplans[i].requestdate.ToString("yyyy-MM-dd") + "]的货源清单供应商配额之和不为100%,无法转交货单";
  7448. info.OptTime = optime;
  7449. exceptions.Add(info);
  7450. continue;
  7451. }
  7452. //获取当前交货计划物料对应的可用采购单明细数据
  7453. var curPurDtls = purOrdDetails.Where(p => p.ItemNum == demandplans[i].itemnum).OrderBy(p => p.CreateTime).ToList();
  7454. //当前采购明细对应的采购单
  7455. var curPurMsts = purOrdMasters.Where(p => curPurDtls.Select(m => m.PurOrd).Distinct().Contains(p.PurOrd)).ToList();
  7456. //当前采购明细对应的送货单
  7457. var curShds = shdzbs.Where(p => p.sh_material_code == demandplans[i].itemnum && curPurDtls.Select(m => m.PurOrd).Contains(p.po_bill)).ToList();
  7458. //数据库中当前采购单明细被交货单占用情况
  7459. var curDbOccupys = dbPolistds.Where(p => curPurDtls.Select(m => m.PurOrd).Contains(p.ponumber) && p.itemnum == demandplans[i].itemnum).ToList();
  7460. //本次计算中采购单明细被交货单占用情况
  7461. var curCalcOccupys = inserts.Where(p => curPurDtls.Select(m => m.PurOrd).Contains(p.ponumber) && p.itemnum == demandplans[i].itemnum).ToList();
  7462. //当前交货计划已分配数量
  7463. decimal allQty = 0m;
  7464. //当前供应商分配数量
  7465. decimal needQty = 0m;
  7466. //当前供应商已分配数量合计
  7467. decimal sumNeedQty = 0m;
  7468. //当前供应商剩余需要分配数量
  7469. decimal remainQty = 0m;
  7470. //存在货源清单,采购单明细可用数量满足当前交货计划,则先计算供应商配额,计算当前供应商对应的采购明细是否满足配额,若满足则占用采购单明细可用数量
  7471. curChaes = curChaes.OrderByDescending(p => p.quota_rate.GetValueOrDefault()).ToList();
  7472. for (int j = 0; j < curChaes.Count; j++)
  7473. {
  7474. if (curChaes[j].quota_rate.GetValueOrDefault() == 0)
  7475. {
  7476. continue;
  7477. }
  7478. //如果交货计划已分配数量>=交货计划净需求数量,则终止
  7479. if (allQty >= demandplans[i].tosechedqty)
  7480. {
  7481. break;
  7482. }
  7483. //供应商占用数量置0
  7484. sumNeedQty = 0m;
  7485. //计算当前供应商分配数量
  7486. needQty = Math.Ceiling(demandplans[i].tosechedqty * curChaes[j].quota_rate.GetValueOrDefault() / 100.00m);
  7487. //如果交货计划剩余数量小于按照供应商配额计算的数量,则当前供应商需分配数量为交货计划剩余数量
  7488. //if (demandplans[i].tosechedqty - allQty < needQty)
  7489. //{
  7490. // needQty = demandplans[i].tosechedqty - allQty;
  7491. //}
  7492. //获取当前供应商对应的采购单明细数据,按照交货日期从小到大开始占用
  7493. var pchPurMsts = curPurMsts.Where(p => p.Supp == curChaes[j].supplier_number).ToList();
  7494. var pchPurDtls = curPurDtls.Where(p => pchPurMsts.Select(m => m.PurOrd).Contains(p.PurOrd)).ToList();
  7495. //送货单占用数量
  7496. var pchShds = curShds.Where(p => pchPurMsts.Select(m => m.PurOrd).Contains(p.po_bill)).ToList();
  7497. //校验当前供应商的采购明细剩余可用数量是否满足供应商的配额
  7498. //采购单明细剩余可用数量
  7499. sumRestQty = pchPurDtls.Sum(p => p.QtyOrded) - pchShds.Sum(p => p.sh_delivery_quantity);
  7500. //交货单占用数量:交货单的剩余需要采购数量
  7501. var pchDbOccupys = curDbOccupys.Where(p => pchPurDtls.Select(m => m.PurOrd).Contains(p.ponumber)).ToList();
  7502. //未关闭交货单需求数量和交货数量两者取最大值,避免交货单需求数量小于送货数量
  7503. sumDbOccupy = pchDbOccupys.Where(p => p.status.ToUpper() == "C").Sum(p => p.sentqty) + pchDbOccupys.Where(p => p.status.ToUpper() != "C").Sum(p => (p.schedqty >= p.sentqty ? p.schedqty : p.sentqty));
  7504. //本次计算交货单占用数量:本次计算交货单的需求数量
  7505. sumCurOccupy = curCalcOccupys.Where(p => pchPurDtls.Select(m => m.PurOrd).Contains(p.ponumber)).Sum(p => p.schedqty);
  7506. //交货单已关闭,但已交数量和送货单送货数量不一致
  7507. var shTotal = Endshdzbs.Where(p => pchDbOccupys.Where(m => m.status.ToUpper() == "C" && m.sentqty == 0).Select(m => m.dsnum).Contains(p.jhdbh)).Sum(p => p.sh_delivery_quantity);
  7508. //剩余可用数量
  7509. restQty = sumRestQty - sumDbOccupy - sumCurOccupy - shTotal;
  7510. restQty = restQty < 0 ? 0 : restQty;
  7511. if (restQty < needQty)
  7512. {
  7513. //当前供应商可用采购单明细不足,生成新的pr,记录异常日志
  7514. srm_Pr = new srm_pr_main();
  7515. srm_Pr.GenerateNewId(help.NextId());
  7516. srm_Pr.pr_order_type = curItem.erp_cls == 2 ? "L" : "";//单据类型
  7517. srm_Pr.supplier_type = curChaes[j].supplier_type;
  7518. srm_Pr.IsRequireGoods = curChaes[j].IsRequireGoods;
  7519. if (curChaes[j].supplier_type == "VMI")
  7520. {
  7521. srm_Pr.IsRequireGoods = 1;
  7522. srm_Pr.pr_order_type = "K";
  7523. }
  7524. srm_Pr.pr_purchaseid = curChaes[j].supplier_id;//供应商id
  7525. srm_Pr.pr_purchasenumber = curChaes[j].supplier_number;//供应商编码
  7526. srm_Pr.pr_purchasename = curChaes[j].supplier_name;//供应商名称
  7527. srm_Pr.pr_purchaser = curChaes[j].order_rector_name;//采购员
  7528. srm_Pr.pr_purchaser_num = curChaes[j].order_rector_num;//采购员工号(采购信息表)
  7529. srm_Pr.pr_rqty = needQty - restQty;//需求数量
  7530. srm_Pr.pr_aqty = srm_Pr.pr_rqty;//申请数量
  7531. srm_Pr.pr_sqty = srm_Pr.pr_rqty;//建议数量
  7532. srm_Pr.icitem_id = curItem.Id;//物料id
  7533. srm_Pr.icitem_name = curItem.name;//物料名称
  7534. if (ScheduleAgreement == 1)
  7535. {
  7536. srm_Pr.pr_ssend_date = demandplans[i].arrivaldate.AddDays((double)(-7));//系统建议下单日期
  7537. srm_Pr.pr_sarrive_date = demandplans[i].arrivaldate;//系统建议到达日期(建议到货日期)
  7538. }
  7539. else
  7540. {
  7541. srm_Pr.pr_ssend_date = demandplans[i].arrivaldate.AddDays((double)(-1 * curChaes[j].lead_time.GetValueOrDefault()));//系统建议下单日期
  7542. srm_Pr.pr_sarrive_date = demandplans[i].arrivaldate;
  7543. }
  7544. srm_Pr.pr_sysprice = curChaes[j].order_price;//系统价格(含税)
  7545. srm_Pr.pr_orderprice = srm_Pr.pr_rqty * curChaes[j].order_price;//订单价格(含税)
  7546. srm_Pr.pr_price = curChaes[j].netpurchase_price;//采购净价(不含税)
  7547. srm_Pr.pr_rate = curChaes[j].taxrate;//税率
  7548. srm_Pr.pr_unit = curItem.unit;//单位
  7549. srm_Pr.state = 1;//状态
  7550. srm_Pr.old_apply_aqty = 0;//已申请数量
  7551. srm_Pr.pr_type = curItem.erp_cls == 2 ? 2 : 3;//申请类型
  7552. srm_Pr.currencytype = curChaes[j].currency_type == null ? 1 : curChaes[j].currency_type.Value;//币种
  7553. srm_Pr.secInv_ratio = curItem.secinv_ratio;//安全库存触发采购比例
  7554. srm_Pr.tenant_id = curItem.company_id;
  7555. srm_Pr.company_id = curItem.company_id;
  7556. srm_Pr.factory_id = curItem.factory_id;
  7557. srm_Pr.create_time = DateTime.Now;
  7558. srm_Pr.create_by_name = user;
  7559. srm_Pr.update_time = DateTime.Now;
  7560. srm_Pr.update_by_name = user;
  7561. srm_Pr.remark = "物料交货计划ID[" + demandplans[i].Id + "]生成交货单采购单不足,自动创建的Pr";
  7562. prInserts.Add(srm_Pr);
  7563. //处理总数量,需求数量
  7564. allQty += needQty - restQty;
  7565. needQty -= restQty;
  7566. //添加异常记录
  7567. info = new DeliveryExceptionMaster();
  7568. info.Domain = domain;
  7569. info.Icdsid = demandplans[i].Id;
  7570. info.ItemNum = demandplans[i].itemnum;
  7571. info.CreateTime = DateTime.Now;
  7572. info.Remark = "物料交货计划[" + demandplans[i].itemnum + ":" + demandplans[i].requestdate.ToString("yyyy-MM-dd") + "]对应供应商[" + curChaes[j].supplier_name + "]" + (curChaes[j].IsRequireGoods == 0 ? "采购订单不足,已生成采购申请并推送ERP,请转采购订单后再生成交货单" : "要货令不足,已生成采购申请并自动转要货令,请重新生成交货单");
  7573. info.NeedQty = needQty - restQty;
  7574. info.OptTime = optime;
  7575. exceptions.Add(info);
  7576. }
  7577. //采购单明细优先级:先PO,按照交货日期从早到晚占用;再DO,按照交货日期从早到晚占用
  7578. //2024-03-05调整:按照采购订单创建日期从早到晚占用
  7579. pchPurDtls = CalcPurDetailPriority(pchPurDtls);
  7580. for (int k = 0; k < pchPurDtls.Count; k++)
  7581. {
  7582. if (sumNeedQty >= needQty)
  7583. {
  7584. //当前供应商配额以满足,循环下一个供应商
  7585. break;
  7586. }
  7587. //当前采购明细剩余数量=订单数量-送货单数量(不是由交货单转的送货单)
  7588. decimal syQty = pchPurDtls[k].QtyOrded - pchShds.Where(p => p.po_bill == pchPurDtls[k].PurOrd && p.po_billline == pchPurDtls[k].Line.ToString()).Sum(p => p.sh_delivery_quantity);
  7589. //当前采购明细被占用数量(已占用数量)
  7590. var occupy = pchDbOccupys.Where(p => p.ponumber == pchPurDtls[k].PurOrd && p.itemnum == pchPurDtls[k].ItemNum && p.poline == pchPurDtls[k].Line).ToList();
  7591. decimal yzyQty = occupy.Where(p => p.status.ToUpper() == "C").Sum(p => p.sentqty) + occupy.Where(p => p.status.ToUpper() != "C").Sum(p => p.schedqty);
  7592. //当前计算中采购明细被占用数量(本次计算占用数量)
  7593. var calcs = inserts.Where(p => p.ponumber == pchPurDtls[k].PurOrd && p.itemnum == pchPurDtls[k].ItemNum && p.poline == pchPurDtls[k].Line).ToList();
  7594. decimal bzyQty = calcs.Sum(p => p.schedqty);
  7595. //当前采购明细可用数量
  7596. decimal kyQty = syQty - yzyQty - bzyQty;
  7597. //剩余需要分配数量
  7598. remainQty = needQty - sumNeedQty;
  7599. //当前采购明细已被全部占用,循环下一条采购明细
  7600. if (kyQty <= 0)
  7601. {
  7602. continue;
  7603. }
  7604. decimal xqQty = 0m;
  7605. //当前采购明细的可用数量不满足交货单剩余需要分配数量
  7606. if (kyQty < remainQty)
  7607. {
  7608. //占用当前采购明细剩余可用数量
  7609. xqQty = kyQty;
  7610. }
  7611. else
  7612. {
  7613. xqQty = remainQty;
  7614. //按照最小包装量圆整:最小包装量为0,则不需要圆整
  7615. decimal yzQty = curChaes[j].packaging_qty.GetValueOrDefault() == 0 ? remainQty : Math.Ceiling(remainQty / curChaes[j].packaging_qty.GetValueOrDefault()) * curChaes[j].packaging_qty.GetValueOrDefault();
  7616. //如果可用数量大于圆整数量
  7617. if (kyQty >= yzQty)
  7618. {
  7619. xqQty = yzQty;
  7620. }
  7621. }
  7622. //生成实体
  7623. entity = new srm_polist_ds();
  7624. entity.Id = help.NextId();
  7625. entity.domain = domain;
  7626. entity.icdsid = demandplans[i].Id;
  7627. //交货单号最后一次性生成
  7628. entity.dsnum = "";
  7629. entity.status = "N";
  7630. entity.itemnum = demandplans[i].itemnum;
  7631. entity.um = "";
  7632. entity.purgroup = "";
  7633. entity.suppliercode = curChaes[j].supplier_number;
  7634. entity.supplier = string.IsNullOrEmpty(curChaes[j].supplier_name) ? "" : curChaes[j].supplier_name;
  7635. entity.requestdate = demandplans[i].arrivaldate;
  7636. entity.needdate = demandplans[i].requestdate;
  7637. entity.ponumber = pchPurDtls[k].PurOrd;
  7638. entity.poline = pchPurDtls[k].Line;
  7639. entity.schedqty = xqQty;
  7640. entity.lastsentqty = 0m;
  7641. entity.sentqty = 0m;
  7642. entity.restqty = xqQty;
  7643. entity.createtime = DateTime.Now;
  7644. entity.createuser = user;
  7645. entity.remarks = "";
  7646. entity.isactive = 1;
  7647. inserts.Add(entity);
  7648. //当前交货计划已分配数量累加
  7649. allQty += xqQty;
  7650. //当前供应商已分配数量累加
  7651. sumNeedQty += xqQty;
  7652. }
  7653. }
  7654. }
  7655. if (inserts.Any())
  7656. {
  7657. //获取交货单号
  7658. var nbrlist = _serialNumberAppService.GetBillNo(domain, "M8", inserts.Count, "", 1);
  7659. if (!nbrlist.Any() || nbrlist.Count != inserts.Count)
  7660. {
  7661. Msg = "NO|交货单号生成失败";
  7662. return Msg;
  7663. }
  7664. inserts = inserts.OrderBy(p => p.createtime).ToList();
  7665. for (int i = 0; i < inserts.Count; i++)
  7666. {
  7667. if (string.IsNullOrEmpty(nbrlist[i].NbrResult))
  7668. {
  7669. Msg = "NO|交货单号生成失败";
  7670. return Msg;
  7671. }
  7672. inserts[i].dsnum = nbrlist[i].NbrResult;
  7673. }
  7674. }
  7675. if (prInserts.Any())
  7676. {
  7677. //获取Pr单号
  7678. var prlist = _serialNumberAppService.GetBillNo(domain, "PR", prInserts.Count, "", 1);
  7679. if (!prlist.Any() || prlist.Count != prInserts.Count)
  7680. {
  7681. Msg = "NO|采购申请单号生成失败";
  7682. return Msg;
  7683. }
  7684. prInserts = prInserts.OrderBy(p => p.create_time).ToList();
  7685. for (int i = 0; i < prInserts.Count; i++)
  7686. {
  7687. if (string.IsNullOrEmpty(prlist[i].NbrResult))
  7688. {
  7689. Msg = "NO|采购申请单号生成失败";
  7690. return Msg;
  7691. }
  7692. prInserts[i].pr_billno = prlist[i].NbrResult;
  7693. }
  7694. }
  7695. //数据插入
  7696. using (var unitOfWork = _unitOfWorkManager.Begin(false, true))
  7697. {
  7698. try
  7699. {
  7700. //插入交货单数据
  7701. if (inserts.Any())
  7702. {
  7703. _srmpolistds.Insert(inserts);
  7704. }
  7705. //插入Pr
  7706. if (prInserts.Any())
  7707. {
  7708. await _businessDbContext.AddRangeAsync(prInserts);
  7709. }
  7710. //插入异常记录
  7711. if (exceptions.Any())
  7712. {
  7713. _DeliveryExceptionMaster.Insert(exceptions);
  7714. }
  7715. await unitOfWork.CompleteAsync();
  7716. }
  7717. catch (Exception e)
  7718. {
  7719. unitOfWork.Dispose();
  7720. new NLogHelper("ReplenishmentAppService").WriteLog("CreateDeliverySchedule", "交货计划生成交货单失败:" + e.Message, _currentTenant.Id.ToString());
  7721. Msg = "NO|交货单保存失败:" + e.Message;
  7722. };
  7723. }
  7724. return Msg;
  7725. }
  7726. /// <summary>
  7727. /// 计算采购单明细的占用优先级
  7728. /// </summary>
  7729. /// <param name="details"></param>
  7730. /// <returns></returns>
  7731. public List<PurOrdDetail> CalcPurDetailPriority(List<PurOrdDetail> details)
  7732. {
  7733. List<PurOrdDetail> newDetails = new List<PurOrdDetail>();
  7734. //获取DO
  7735. var doLists = details.Where(p => p.PurOrd.StartsWith("DO")).OrderBy(p => p.CreateTime).ToList();
  7736. //获取PO
  7737. var poLists = details.Where(p => !doLists.Select(m => m.PurOrd).Contains(p.PurOrd)).OrderBy(p => p.CreateTime).ToList();
  7738. for (int i = 0; i < poLists.Count; i++)
  7739. {
  7740. newDetails.Add(poLists[i]);
  7741. }
  7742. for (int i = 0; i < doLists.Count; i++)
  7743. {
  7744. newDetails.Add(doLists[i]);
  7745. }
  7746. return newDetails;
  7747. }
  7748. }
  7749. }