From 0565053d7a03b3aa855e272033db7f8c2e2141b8 Mon Sep 17 00:00:00 2001 From: Deena Date: Fri, 1 Aug 2025 22:14:43 +0530 Subject: [PATCH] leads of sales and inside sales matched --- sos_inside_sales/__manifest__.py | 1 + sos_inside_sales/data/lead_source_data.xml | 16 ++ .../sos_inside_sales_leads.cpython-310.pyc | Bin 5713 -> 7062 bytes .../models/sos_inside_sales_leads.py | 97 ++++++-- sos_inside_sales/security/ir.model.access.csv | 2 + .../views/sos_inside_sales_leads_view.xml | 42 +++- .../__pycache__/sos_fir.cpython-310.pyc | Bin 10591 -> 10711 bytes .../sos_inventory_customers.cpython-310.pyc | Bin 692 -> 1280 bytes .../models/__pycache__/sos_ir.cpython-310.pyc | Bin 12992 -> 13012 bytes .../__pycache__/sos_material.cpython-310.pyc | Bin 5118 -> 5210 bytes .../__pycache__/sos_mon.cpython-310.pyc | Bin 19786 -> 19814 bytes .../__pycache__/sos_mrn.cpython-310.pyc | Bin 12326 -> 13048 bytes .../__pycache__/sos_ncmr.cpython-310.pyc | Bin 25072 -> 25631 bytes .../sos_testing_parameters.cpython-310.pyc | Bin 4635 -> 4646 bytes sos_inventory/models/sos_fir.py | 7 +- .../models/sos_inventory_customers.py | 20 ++ sos_inventory/models/sos_ir.py | 7 +- sos_inventory/models/sos_material.py | 2 + sos_inventory/models/sos_mon.py | 8 +- sos_inventory/models/sos_mrn.py | 47 +++- sos_inventory/models/sos_ncmr.py | 30 ++- .../models/sos_testing_parameters.py | 2 +- sos_inventory/security/record_rules.xml | 5 +- sos_inventory/views/sos_fir_brr_view.xml | 2 +- sos_inventory/views/sos_fir_view.xml | 6 + sos_inventory/views/sos_ir_view.xml | 1 + sos_inventory/views/sos_material_view.xml | 1 + sos_inventory/views/sos_ncmr_view.xml | 54 ++++- .../views/sos_testing_parameters_view.xml | 6 +- .../sos_case_diary.cpython-310.pyc | Bin 20032 -> 20048 bytes ...s_sales_achievement_report.cpython-310.pyc | Bin 23335 -> 26093 bytes .../sos_sales_leads.cpython-310.pyc | Bin 3860 -> 4604 bytes sos_sales/models/sos_case_diary.py | 3 +- .../models/sos_sales_achievement_report.py | 224 ++++++++++++++---- sos_sales/models/sos_sales_leads.py | 89 ++++--- ...erformance_report_abstract.cpython-310.pyc | Bin 3824 -> 3994 bytes .../business_performance_report_abstract.py | 19 +- .../report/report_business_performance.xml | 74 +++--- sos_sales/security/ir.model.access.csv | 2 + .../sos_sales_achievement_report_view.xml | 22 +- sos_sales/views/sos_sales_leads_view.xml | 21 +- ...action_plan_summary_wizard.cpython-310.pyc | Bin 2249 -> 2249 bytes .../sos_sales_achievement_wizard_view.xml | 35 ++- 43 files changed, 646 insertions(+), 199 deletions(-) create mode 100644 sos_inside_sales/data/lead_source_data.xml diff --git a/sos_inside_sales/__manifest__.py b/sos_inside_sales/__manifest__.py index 5003d2f..87da682 100755 --- a/sos_inside_sales/__manifest__.py +++ b/sos_inside_sales/__manifest__.py @@ -15,6 +15,7 @@ 'data': [ 'security/ir.model.access.csv', 'security/record_rules.xml', + 'data/lead_source_data.xml', 'views/menu.xml', 'views/sos_inside_sales_leads_view.xml', 'views/sos_target_tracker_view.xml', diff --git a/sos_inside_sales/data/lead_source_data.xml b/sos_inside_sales/data/lead_source_data.xml new file mode 100644 index 0000000..40a43c7 --- /dev/null +++ b/sos_inside_sales/data/lead_source_data.xml @@ -0,0 +1,16 @@ + + + + Website + + + Expo + + + Cold Calls + + + Linkedin + + + diff --git a/sos_inside_sales/models/__pycache__/sos_inside_sales_leads.cpython-310.pyc b/sos_inside_sales/models/__pycache__/sos_inside_sales_leads.cpython-310.pyc index 8a597fd0b11dd4019af7f7d55db709a460fb80a3..434cacdbf7c088ac2812cddfbaa300272287d25b 100644 GIT binary patch delta 3574 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 diff --git a/sos_inside_sales/models/sos_inside_sales_leads.py b/sos_inside_sales/models/sos_inside_sales_leads.py index 96dd073..f73eb95 100755 --- a/sos_inside_sales/models/sos_inside_sales_leads.py +++ b/sos_inside_sales/models/sos_inside_sales_leads.py @@ -20,31 +20,44 @@ class sos_inside_sales_leads(models.Model): moved_on = fields.Date(string="Moved On") location = fields.Char(string="Location") website_url = fields.Char(string="Website URL") - vertical_domain = fields.Many2one('sos_vertical_domain',string="Domain / Industry", ondelete="cascade") + vertical_domain = fields.Many2many('sos_vertical_domain',string="Domain / Industry", ondelete="cascade") line_ids_contacts = fields.One2many('sos_leads_contact_lines', 'ref_id', string="Contact Details",copy=True) remarks=fields.Text(string="Remarks") linkedin_profile = fields.Char(string="Linkedin profile") - products = fields.Selection( + # products = fields.Selection( + # [ + # ('BHMS 1.2V', 'BHMS 1.2V'), + # ('BHMS 2V', 'BHMS 2V'), + # ('BHMS 12V', 'BHMS 12V'), + # ('BMS-HV', 'BMS-HV'), + # ('BMS-LV 100A', 'BMS-LV 100A'), + # ('BMS-LV 40A', 'BMS-LV 40A'), + # ('SBMS 55A', 'SBMS 55A'), + # ('MC 250W', 'MC 250W'), + # ('HeartTarang', 'HeartTarang') + # ], + # string="Product Interested In") + products_interested = fields.Many2many('sos_products',string="Product Interested In") + service = fields.Selection( [ - ('BHMS 1.2V', 'BHMS 1.2V'), - ('BHMS 2V', 'BHMS 2V'), - ('BHMS 12V', 'BHMS 12V'), - ('BMS-HV', 'BMS-HV'), - ('BMS-LV 100A', 'BMS-LV 100A'), - ('BMS-LV 40A', 'BMS-LV 40A'), - ('SBMS 55A', 'SBMS 55A'), - ('MC 250W', 'MC 250W'), - ('HeartTarang', 'HeartTarang') + ('Product', 'Products'), + ('Project', 'Projects') + ], - string="Product Interested In") - source = fields.Selection( + string="Service Type",default="Product") + project_name= fields.Many2one('sos_projects',string="Project Name") + status = fields.Selection( [ - ('website', 'Website'), - ('expo', 'Expo'), - ('cold_calls', 'Cold Calls'), - ('linkedin', 'Linkedin') + ('Open', 'Open'), + ('Close', 'Close'), + ('New', 'New'), + ('In-Progress', 'In-Progress'), + ('Qualified', 'Qualified'), + ('Unqualified', 'Unqualified') + ], - string="Source") + string="Status",default="New") + new_source = fields.Many2one('lead_source', string="Source") meeting_scheduled = fields.Selection( [ ('Online', 'Online'), @@ -52,12 +65,24 @@ class sos_inside_sales_leads(models.Model): ], string="Meeting Schedule") expo_name = fields.Char(string="Expo Name") - move_to_sales = fields.Many2many('res.users',string="Move Lead to") - cc_mail = fields.Many2one('res.users',string="CC to") + move_to_sales = fields.Many2many('res.users',string="Move Lead to", domain=lambda self: [('groups_id', 'in', self.env.ref('sos_inventory.sos_sales_user').ids + self.env.ref('sos_inventory.sos_ce_head').ids)]) + cc_mail = fields.Many2one('res.users',string="CC to", domain=lambda self: [('groups_id', 'in', self.env.ref('sos_inventory.sos_sales_user').ids + self.env.ref('sos_inventory.sos_ce_head').ids)]) move_div_display = fields.Boolean(default=False,string="Moved to Sales") line_ids = fields.One2many('sos_inside_sales_activities_line', 'ref_id', string="Action") week = fields.Char(string="Week") reporting_to = fields.Many2one('res.users', string='Reporting To') + sales_type = fields.Selection( + [ + ('Domestic', 'Domestic'), + ('International', 'International') + ], + string="Sales Type",default="Domestic") + country = fields.Many2one( + 'res.country', + string='Country', + default=lambda self: self.env['res.country'].search([('code', '=', 'IN')], limit=1) +) + @api.model def create(self, vals): create_uid = vals.get('create_uid', self.env.uid) @@ -122,14 +147,29 @@ class sos_inside_sales_leads(models.Model): 'transferred_on': fields.Date.today(), 'location':self.location, 'website_url':self.website_url, - 'vertical_domain':self.vertical_domain.id, + 'vertical_domain': [(6, 0, self.vertical_domain.ids)], 'linkedin_profile':self.linkedin_profile, - 'products':self.products, + 'products_interested':[(6, 0,self.products_interested.ids)], 'source':'inside_sales', 'expo_name':self.expo_name, - 'lead_generated_by':self.env.user.id + 'lead_generated_by':self.env.user.id, + 'sales_type':self.sales_type, + 'interested_in':self.service, + 'project_name':self.project_name.id }) if new_record: + if self.line_ids_contacts: + for contact in self.line_ids_contacts: + self.env['sos_leads_customer_contact_lines'].create({ + 'ref_id': new_record.id, + 'name': contact.name, + 'dept': contact.dept, + 'email': contact.email, + 'mobile_number': contact.mobile_number, + 'set_as_primary': contact.set_as_primary, + 'linkedin_profile': contact.linkedin_profile, + 'remarks': contact.remarks + }) self.move_div_display = True return { 'type': 'ir.actions.client', @@ -151,6 +191,8 @@ class SOS_Leads_Line(models.Model): email = fields.Char(string="Email Id") mobile_number = fields.Char(string="Contact Number") set_as_primary = fields.Boolean(string="Set Primary") + linkedin_profile = fields.Char(string="LinkedIn Profile") + remarks = fields.Text(string="Remarks") @api.model def create(self, vals): record = super(SOS_Leads_Line, self).create(vals) @@ -176,4 +218,11 @@ class sos_inside_sales_activities_lines(models.Model): ref_id = fields.Many2one('sos_inside_sales_leads', ondelete="cascade") action_date = fields.Date(string="Action Date") - remarks = fields.Text(string="Remarks") \ No newline at end of file + next_action_on = fields.Date(string="Next Action On") + remarks = fields.Text(string="Remarks") + +class LeadSource(models.Model): + _name = 'lead_source' + _description = 'Lead Source Master' + + name = fields.Char(string="Source Name", required=True) diff --git a/sos_inside_sales/security/ir.model.access.csv b/sos_inside_sales/security/ir.model.access.csv index fbb50d2..bc0d9c7 100755 --- a/sos_inside_sales/security/ir.model.access.csv +++ b/sos_inside_sales/security/ir.model.access.csv @@ -4,3 +4,5 @@ access_sos_inside_sales_activities_line,sos_inside_sales_activities_line access, access_sos_target_tracker,sos_target_tracker access,model_sos_target_tracker,base.group_user,1,1,1,1 access_sos_leads_contact_lines,sos_leads_contact_lines access,model_sos_leads_contact_lines,base.group_user,1,1,1,1 access_action_leads_report_wizard,action_leads_report_wizard access,model_action_leads_report_wizard,base.group_user,1,1,1,1 +access_lead_source,lead_source access,model_lead_source,base.group_user,1,1,1,1 + diff --git a/sos_inside_sales/views/sos_inside_sales_leads_view.xml b/sos_inside_sales/views/sos_inside_sales_leads_view.xml index d97ee31..04c6dc6 100755 --- a/sos_inside_sales/views/sos_inside_sales_leads_view.xml +++ b/sos_inside_sales/views/sos_inside_sales_leads_view.xml @@ -7,10 +7,12 @@ + - + + - + @@ -20,17 +22,21 @@ sos_inside_sales_leads - - - + + - + + - + + + @@ -50,18 +56,24 @@ + - - + + + + - - - - + + + + + @@ -77,6 +89,8 @@ + + @@ -87,6 +101,8 @@ + + diff --git a/sos_inventory/models/__pycache__/sos_fir.cpython-310.pyc b/sos_inventory/models/__pycache__/sos_fir.cpython-310.pyc index 2962655c99ad31486850c6a735af48a463e58f31..26b6fed1bba3d36dcfed420e84dcd0c3393259a1 100644 GIT binary patch delta 1524 zcma)*ZERCj7{~i`ZMU^+?aJ7?tz9YXt)c=oaJv)t|6ZFg(e?X)t6 zA}^atf{5lpQL?}ah|EL*Z$gG4;x}JDppM|668!*yXf%G|i-`%I=M)mZ;r;Nt|NFe1 zbDrniU%M8&9Z|d8Y7h_B?i+e9c-9dFxTDuYrEzEa@M_k~s#ylB*`L<4Mopj1U>g$9 z^Q5|Vwu-eRfVHxX(}pSNsTP(R*2dad2kT6jSQqP-_NUk;_RO@Qr&jpuSPOeLVPwy- z=cTV++FlSlg1P#+WMJPm81~HXzCj zvLTt#%rrJEJR8_Zw;>SLeWriR`P=P{8jnmUTwS(ai7VT4?|nea|thRj(4QS4a zTa&p1_d; zC|zQ%6jDKp^Bqfs0zCMbGY8K&Ghsx!R}141E;x_bWD$zt(qny8$S{3|^_lD%fEfPl zdK@&}wd5lJ4d-)$unqsn`4nRM;iV>Uj#I3S@CxBo{4BSr{B@G+2yX}kOsSpi6FO;) zsiQ2UMiec~_o6qi3=UyK-qocO^`Oq%QxM<0lb0XH1$J>zZ5nRs6wUx#ct^pCOzjd`{2_ zG(!FbVI|=LLALiKsX9VELEhE#q~-|c2yz17kUB-%vhW3=Z{hCceptZj5-)zW{4`wF z$5yz&_kayxqSy=P@M3X5OzgMfp!vEebqD<=g>YT3E@=Rt9ATQqVo8^>Roq~uFRX?J z21BDtM2)3>AoER;l!50N@pfT_Yfwn*v|GyiOjg@~`s@b%-hu;=e>|ij&vV_Pmn7{-M hV-~o9-^PpOT~2B|r1zN6Oz=6BHUrp>7to#obVzk3g?|>8Z@pQZ7VA6_I9^?9@e5`C7xWF&{Sv z0UB}GatRu+xhRM8MMtfA-X;#mw-VYhXZ;@9@^!Xt0NWAoI_*r7UnijHv)R6L1>8=? zPFxI?7^{Sg;~x7lQ<@UI_^$nKv=2HPb$orxaSs?_LX^;THEWWbv}wV|`83MQ_dQkQ|Cl zI5TMW^uY;y$rFQ%_?_p5(C14(hIwrDDlmal-b&$I_tx4cXz|YpX9#EULEn0@01f}7 zFfQYWuN7iA=i3Dz;X{6R@t|Ap+u@r=~ekrs*u1Uc(Vq|VTmj8}xbj(>)Na0UN~`0%lNr%ZFg)0{YMa-!kBKLWSe z2fD*Pn8E6BR9uk~t~6?*{3ad`mx4wu^FM~mLA>sNulC*gZmx+0BR&#oYPn5ok;lsk zbn7eUe4W(Sgx?7U!ViRN@;Hk^F5_aP6c)wWr{i=KzM9}7{6zSfut1=p^9q5sXc7Ov wdy!+5U(N+w2>FalqTY-X}K-*euxEf1Edh&l?F$UI!BoADlm2GU`dDN+Z4?}bv41DD)d;<7m=}~N#p8@JA-=O~mkKj9aTsz*7z6=x?p=nN;Kqh|h zjQb{{1{c^oF6_4ZcOQ|YD`dOLIO(ObL1H4(W}3yEwBjZsamHCp-w^gX6;j+M+rxfk zo7`;1GHEbMME8}DJZ;rYr;oO4wNN{CCN<95J;t?@v6l7(i+R#mdSf29>Wtd}8jEg+ zaqd~}CB{dxTA*FQvIFg&#F@}Ri}fO#Lzfo;jM0N=o!7M2R2SCmr5dI>_b=Kx)VU~1 zvRH^HI-h)p&+l9@mL*ey7$~C>3SoeX@TyaS0Yoq~<;~qWnxj9ZpkE#TuHU7OG1GsOT1l ZO>TZlX-=vgBS;@evj`IhBM+k(GXU?z8NmPm diff --git a/sos_inventory/models/__pycache__/sos_ir.cpython-310.pyc b/sos_inventory/models/__pycache__/sos_ir.cpython-310.pyc index fffd990d7836b34e56615f40114a972d12264527..58cde96c6cb39f1f4754ef2ce6e8efc9dccacb32 100644 GIT binary patch delta 1398 zcmb8uZD?C%6bJBon%p+8ZPTQkYtrU+X>AjeEGvR2Ecnv7svlIkFNTe-=HAs5n$#y( zW^3C`TdRz=77q+$^<{NaHwB%M3T~o^Uj`0g7GJKeLqSo&p`e3pMScEPH}PZh;m7kl z_neb^&b{|TW5w{7{C|7v=cQ^D<_tuozVr@M5g=^l3={Xp<0 z^6*E&?%*+}@XG`-0Vcsd{w*0|EtHn^?hW<&AIISnlDJ3A@W;U|GJhZ$OT|tM6Rux@*@up8F^EjLH2^( zc%uEZ4FA3TI34E~JF;y^5+}ikB>wL}7jS?Y;*33s!1V!&;Jz$X&-WKgmaAvLG|a-V zA>KpOyPWNuq__F~&P{;|!rXd|RsigK;G zrngNixv0LWPl?C)P~tY4=W~fx;>ucL1Np|h+a4V$h*3@UzzxY!dY)&KPty`NrZW39 z@iqSS8*mPkz$$Qn??4;q0pCh2XK_Fd;uq}k7_FMSil#AW2(gT#qriT~cVhJd*akA- zA~3-pAh{Fn0zXPDuVLS6zb?luoH)J&TqJSxYU(=AWw}2fx8=mM=?;&NT;w62Q(Wd$ z`sds{g0Fxz@H+TYvP1kO9c#>&hDS<8Jg9=6zV_Y{s#k#!66E(Qn+GbW1~vTf=37;_ zT%O|P&8gk%9-6Sc1K53^WRHoX7d05 delta 1443 zcmb7^Uu;uV9LMijd)Ka)uJn)FT-UYTI=3#}=<0)s2~%{+G(1Sa2N(2OdoQKSdhc?2 zNo3iEx;YkO=HM3-Vsv&9K|n}M1tFl(7o#Q$4@2Tb)TmFsAP+{2(|EoY!T7j7e0t8k z-{1F~@9&&;MgLg$n|{Af5}yU5uxtK3|LS_*Nimz0MkW3@g@cu*?M#|-Gif4VDb;nF zZ22eMGi;e&3v$*-{?HQvk2+=+i#oSuopY1ZSg6d}$qo(rUby9SA9aK`Hw_9Wm*eEE zHfV0kH|c`YRQMjI(5Y~)g-?lsqi*gOUwj(a3p_{HGZA_-0I4>Di+U1zq_4$HTG7VuVWVPm|9Wr}`tmqIs zNN1zx*ivnGTa;~l3+9J_$AGtiC19I??XB!Ass&Ti`8#-a6gUP91IKG$#ugddPfx`M z*%G}GA6A_D!+3dwevOZ`?!(Y=MyvT|;8CDPT4HPTfEe11<-DcyQhrP=igt|m@6(~~j^HWC z8cK$y8fAJO!2OD!2{VOO3Pb+uH^i)-^WC3;4?o`>p1U>;Zi z6krAT2KZK@>wV4iY0nD#k<|VN=xTZ{-dc@nZOcrHY3;Mp3>#_F;#y)>8i{GiZBn{} z7J4_aMY`DA&R(ru>uqKf&OFOrrO0_jzyy8( zT)@vj5*Px060qGyUbN&I<~U^A^N3;TA{ak|M@InX20V;W6?h290yh8)_#J570X_-1 zfjY#b0#=( zN5L$Qn+DFPr1jsv#^N_A)&n9asK-bKJb)Kype+OU%ZeDDqc1k}J-y~Gap$T#eelDu zij|y>IL&a<{}nmnO-C4XHlmY{Hrq-0{ w673(zXlu@7dv5&^tSMI@C~|#YuW6o$DoIHkZ0C{|2% z;@Njfmuw$?6JE=34>An_=3pLtklpuIZfa614k<{(0^Dy9P`H+W#RjQNYPSxi;K3n* z9OQRBZ%F0#o~KTr086{R${p@bLy`LeEW^W|pXAyMJmO!J;Bik$?RmVOO1k8UJ#mAj zVs~8p;GK#IuGrRWS1fBbuLaX`g(Ztl^KoDKOHIwFNAr4Ji-~lEOBC-xWsdImA%&1M z`{f%W872+aNUGZ!P7*T9KKd6!8O+TgavTfn*grwCY$A|JW>HLYxMAIFR!vZC$EvNV z+f^eb&{;G@UejKOew#6Fl)9e-SIG4jn2|Q9R@YzBJU`F^Vg+SUHyu|rG&6Rh*NfKJ zad12^(2OPID0$AF$^~+ly_c6c|Hx4Zo6;3_UOC{G`l?(eW%g6)@R{48YQS&fB267RkdbRZM&u!hN=#X{tSb?HAuV~;;-#6HC*HV%7{+~0F!_+36w@LE6fw{=e2GS-P~s#drKAA@t;$E6dLIBl1FL2L1))ts^TEYt?&$M2aQ<^xpeCe*C@{jqc_&UsY3*c-{}b zZvPy5r-kye%;yJ&zwYcHS|DXoAyqPMBci>HH^<3!8#OP{iLJ|I<|86ENNrtugPK=1 zq!uExq`sbLP73uZxhZs++#`0X!Cn6znrX8H+(@l~?p5X&=f7 uz!Prjy7CgrDu1D0JlemH{ta&m+2-H%(`b|b(#wNz-Z$W1BR3A8K+Ai1*{KNt diff --git a/sos_inventory/models/__pycache__/sos_mon.cpython-310.pyc b/sos_inventory/models/__pycache__/sos_mon.cpython-310.pyc index b5c6dc084425021ab40d60ecc9fb458028173d80..e58ea797cb0c10f15f7e6b86d32592e1bcbea42e 100644 GIT binary patch delta 800 zcmXX^SxA&o6rS%N=XV)rs&UJ4%yC>tCzqK~+}Balu`*25BoLR}(y@OuQmmj}5)!L} z1(Gj8Q4dCO=^?_Okm%5k>bz>Sft@cxgs1+^0vh3UH>FpmJXkXTN z2RsU!my-btTlZ~|G>VBQP(#24SrBC}tp&_zErROB%@CRk3ZZ#zI5hNH8zm_w_FF3f z4)!N-1TfQ(z7ZL0L4RJ&wR%IH1`e7Ii$f|~2#bk}IsFu0F*sjGY3m2}l%R zrch%ZoHS<(qGQI6U_Yo-BdTtdSJS4d-D1i)dSR@<8H$S7k96vdaHEMHa&$0_Nsj;* zw~-|u$Y9}-Exb7z*|UUIs*7Tr`_oN?us|nshOkKAa!Oz#NA6FokTvfm-jh0i z2A^my|2EcHcR?JGN|y?E^9kH3yvlh|ksTY%Thswr)KzLIy(EY>iXA+bP%;5Mn<+7i zfxRhB;gZgEln=hgwS*#amAyh4MVI$;{Yv>NX4$EV6eOo{o8cX`Y^po2NQ!*cEF02dL-cq5uE@ delta 724 zcmXX^T}YE*7~T1%n@+cCM8?cEb)RcGH=Ubp>inC|a!ZLc6Ds^^q*=~BwQ?8{{TPK9 zKKg{1~R9QeO zTT{0P>iO92o`@8tX3aH~n~NkHt!O5YO3xBJh@qtfBWV)$Snd=p*&4!@04<7$2=MC%3zVfNM=J3@~GJm)ogI0UvWYq zou?H;75Zp*@;=z;N^%efX@;YdrR>l_RmycLfw@y!z~|lDIg3R)ZDhO_P5ZIV&YITc zMsJ!QSu~y&Rmpou7V@UQ1@y&1I*BHK_A{yVqrPlR9pBH zb5vP0htFj6P2eki^gY2cyIL#)b{Z|&&i!7M+~M`%QYXH%q0-~>`Kx6?PWj7kBazLO zn`COuZ|9V?;s_ixP%(>QYO4GIKluV(oPQqpf=PC(%8o1tk0iS3K%mN0D;*06`nh@Gdugtdi_{GV>^x$Z|XRWl{an3({bFyCD^o1++?%aJKn7Aowe_d z>qlqn(4>_hp|X3^R%%UaSEvv~d07a4w1ALWM0raHp%I}F3TmLVfIuz8JkGhh8yirB zRD`Yh=G=47{qC7_&pCIWKmD!|%me~n3I3Y9E}p&EGaGcs{1>k8kf*oMjs-#w(asCf zd2(W_v3Y(AJq(&IdY8~_15Gdnf%6y$9aA z=)JTL-tVKw=?Qq>LHp@_@V=9t?2)3U96g)K#$st^I&PHGZ1GX$6I!dIrBi0i%p?f9 zSolMC-SF&(C;N8*TN;#DjyJTFO`|xd*iuZPBuU`yN=i9+gVuFGIvL5yAgi`KsKMig zM~BBlWE;;|H43oGxf|pwWRsol|li+g)Jr6d0%tD`I{s^+@Fp5a6oa(V5#^p+lnifIXa3&jusyoF-+?CZ?4G> zBpu()(LgflWqvSsf<>|zPG%jwICeb3`u_NE*70NqrjrE&1(^aj=VCb22a2;YjPje} z!q`BP1<)x0LEJAC%b1C?aWiSe^4YZ+v|03Alf4B0b=gJy#08lD*KUN}n!NvC)!I^6 z)8v&p?Qdb#E4zL?RaMO9wtwG>w|jp;;#~1{sO&D-k>BUrOiuAfeIEsFmA{>w;Ya+N z{Hzn^*kOb&{?xiU{*s@Dgzm_Si7kOnGR$*!z7;M>C;zDX2qglQgcDdkUxLu7`3CfrTd@f+c)X{ta;KrvC*kjyq< z#!^y+#YE;^RHYhqFDUtfplX#guVR)DYE++-7YMAB4@fiQ|FU)m;_p4o_uZ*_xPnS0}fs3G={clc2mYqDdVx!OVmWu7< z8b4hT+o;UQ411FZo{)=9puXrtiyeafmiU_$jY>cG5Q>y}MYbg&u{!w1$nNk*Kytj$ z+GETZfM&!f&qel@OC;8=?PAH43HIeB!D$)RsmS6@pGttPf zBpvMx%Zz6Y;h^IijmM~wNM%zQxSNuO6}K!VTBW0ovy^45XlW^vT}A?z8BZH5hg%#) zm_xv33#|>pK;u@xVBM&kN4UagYfJC=6p9Z5L`y_lWG2XPFOCeSEX$xyMPe*#Wq=pL zXpMODQiu#vDJ>P(!~ zJT7a&8U1e4XitL&qJickEP{CkO|~H1DeR7dhgO_TvQwyY30<-Cvp#7T?oJK7q_S)e znruWEMDQYvAv}ce2*S$<-$DrRKj@|WXN?}h_#2IVD&82aeD9hFDP26i<~c$x@};Kz zf!~4c71>d`GguYOjej;XB3A`LHBvm|dHVv2d6`5V)_03UP zBfP7*pY-zQnE(8@pLx9@_0#-Z$Kl9@_fDq&}ZIxd9 zjwu|5_}6c1{hyCO1fPYGP_)}pl*$mw5k#~_OjiUET@U1eFX_5k0hYsjqP3Y+EI!j3 zCe_O!d+{+Q delta 2830 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 QZt~N%JcBbbY+T@f0gVUUP5=M^ delta 2745 zcmah}dr(y86~Euz7jJo`NQ9u7MqOZet6&i^J|luC2(k;V>z)-@VHfW5h~%ytBgQmB zV*H{(1!ZHbZDJpKO~kh;#+X(owYIgxq3rDWA&qrB|H##~(!k;fXy-f$-I2n_{Sd=!OJtqeiz#3Q!RZ!ipvzE9_?kL3T zAPnXqUWm99Y6PxDya@5*upXxLGwWjXmp~m@!G_uO{d((C!89PVA;c_0CI#%U5pe?Q zmkaE8fLFLo0g80FQLxrF7PE5#J1r(9|zmD+Fo| zq1A}u8YOVQ%3uq$KosUzx&qWutLSJACQ$btJe;~;i?|fL(1w`0uR=`IYR7EZT8$_P z6ro%fQu;#58lmif&XBSe@%_22pQNj!{^`iBkkBfG-2&5*wn@VJNx}y7sh20Qm#xqv zdf6~3ZbzT$J{79F5pgM~0#jWF;)x3dm~|5ZCl>Q#v2755r(rv86GVw;U2n# z@d@S_GT(#ag6R;<_mTMlyp9a^-zf^cfz%23p-Acy%#Yy5K^cAmCk59X;!Yu_!D+!g z8RFhV?kzYYxUDb(XR+TNI0xtP{S;h)i}+UI5?sc&AFjaL_}&ITh0$Iq)*67T@D37B z!?h~Od|f+W>I&zHaoO54akm-!JFiLDYwA?xJvybEf0mHJKGvoszM~76)mhUdFegg> zbddZRYPfr*KU2-zBm1fed*-9H;FCq1;_8^CWQc)SeWk5#;c@b^cBeRXM3h0%0P4& zvJoXBqU#)k97NHGsN@OAMPx*jh3FLIi5icg|0n+b)Q2qB)tuoRHP@Z(P6;w5p_hxX z+aWgh0h@>HhdeGh)o|W374mt0@(f)8%;B}k7B-jfOm1ZJ_}`LeEiO!!hD)Fb=65U{ zE>#PHOqJY=@G-)7pm@+2Wd1p@07}$3ZsQ>d77pp46c!EYsw9vm9`oZ`?ZZrFU+}t= z7bEZC|5Zgr^B2&@Q@+x(#oCuM)|ps0uQ2~nAI0=CFHFD4j%)YQHO6}Q>zU)MRXc9! zW6aMBvj4#P_`^9v>}5WZ)5iw+(%j#(W89o~lbzuI$~(YL@t5* zzl%0VNO+S6!g$Vw27b&4UvZ@^C_ z(r@@iMcpuI8HfrHMS9f`G^MbKsYgQ$Oo3R4gZM!mB+xd@iTvz}xdx>MFU&t%QO{eR z*l!LSi*h(Sn!O%-qvGvsQ#dWB3}-ZEQo!Enb17qn7H?y-hv%%E$~#uBnl?<`ufQ}T zi(q=(>cp>pJi^HDuC%f3T6tNa96uIb?(l5QYel1MqrrFb!SY8~7e8OV8uu7kad75X zBp%`Pwzj%F9X>^&Lt~L~w6!VTE=P;q*WBn)eEc63M~od*VFw>tJ%h#a%c~pt?8=Ji zu`HJ1=faFkHqj-F_hO@ni;*K_DG=7p4_6i+{h(4#>m~J0GS8BEk9yoio{qfT{HwL8 z>;;}&m2J?Fy~WF`(qxVCPbw4m_Nv~<)0FxqnYVasba;8HOZ&qwdZON>YA~#%xmdBRLiguFWpoXP3*~3_j%sKWR(gcdQonK99>wFuaSY zu{_n*_U&JgNME7sql=DADlPsrquxk*M(c_+!El_)e_g(fv-X!U}t zMY(prVKEwo`ctSWh3-9Oj<(yKEe@a0>1t`Q+b3ou1|>!&rbWa3v&^SED{$~$r!A5` YP=!7tWfcD!lK7|2EJH`<7IO-kynsn$b2ZayegLAK37h}` diff --git a/sos_inventory/models/sos_fir.py b/sos_inventory/models/sos_fir.py index a3daf2b..e2302b6 100755 --- a/sos_inventory/models/sos_fir.py +++ b/sos_inventory/models/sos_fir.py @@ -63,6 +63,9 @@ class FIR_Only(models.Model): cloud_data = fields.Binary("Cloud Data", required=False, attachment=True) cloud_data_filename = fields.Char("Cloud Data Filename") + + firmware_data = fields.Binary("Firmware Data", required=False, attachment=True) + firmware_data_filename = fields.Char("Firmware Data Filename") @api.onchange('batch_size') def _onchange_batch_size(self): if self._origin and self.batch_size is not False: @@ -75,11 +78,11 @@ class FIR_Only(models.Model): ] self.testing_parameter_line_ids = line_values - @api.constrains('test_log_filename', 'sd_card_data_filename', 'cloud_data_filename') + @api.constrains('test_log_filename', 'sd_card_data_filename', 'cloud_data_filename', 'firmware_data_filename') def _check_file_extension(self): allowed_extensions = ['xlsx', 'xls', 'csv', 'zip', 'pdf'] for record in self: - for field_name in ['test_log_filename', 'sd_card_data_filename', 'cloud_data_filename']: + for field_name in ['test_log_filename', 'sd_card_data_filename', 'cloud_data_filename','firmware_data_filename']: file_name = getattr(record, field_name) if file_name: ext = file_name.split('.')[-1].lower() diff --git a/sos_inventory/models/sos_inventory_customers.py b/sos_inventory/models/sos_inventory_customers.py index 30814c4..b9c0615 100755 --- a/sos_inventory/models/sos_inventory_customers.py +++ b/sos_inventory/models/sos_inventory_customers.py @@ -13,3 +13,23 @@ class sos_inventory_customers(models.Model): customer_name = fields.Char(string="Customer Name") customer_location = fields.Char(string="Location") + @api.model + def create(self, vals): + new_name = (vals.get('customer_name') or '').lower() + + if new_name and len(new_name) >= 5: + existing_customers = self.search([]) + + for customer in existing_customers: + existing_name = (customer.customer_name or '').lower() + + # Check all substrings of length 5 or more + for i in range(len(new_name) - 4): + substring = new_name[i:i+5] + if substring in existing_name: + raise UserError( + f"A customer with a similar name already exists: '{customer.customer_name}' " + f"(matched substring: '{substring}')" + ) + + return super(sos_inventory_customers, self).create(vals) \ No newline at end of file diff --git a/sos_inventory/models/sos_ir.py b/sos_inventory/models/sos_ir.py index 9b3f22c..005e1aa 100755 --- a/sos_inventory/models/sos_ir.py +++ b/sos_inventory/models/sos_ir.py @@ -154,7 +154,7 @@ class SOS_IR(models.Model): self.line_ids_material = lines except Exception as e: - _logger.error("Error processing po_no: %s", str(e)) + print("Error processing po_no: %s", str(e)) @api.onchange('wo_no') def _onchange_wo_no(self): if self.wo_no: @@ -170,7 +170,7 @@ class SOS_IR(models.Model): self.line_ids_sfg = lines except Exception as e: - _logger.error("Error processing po_no: %s", str(e)) + print("Error processing po_no: %s", str(e)) @api.onchange('wo_no_inhouse') def _onchange_wo_no_inhouse(self): if self.wo_no_inhouse: @@ -186,7 +186,7 @@ class SOS_IR(models.Model): self.line_ids_sfg = lines except Exception as e: - _logger.error("Error processing po_no: %s", str(e)) + print("Error processing po_no: %s", str(e)) def action_report_ir_btn(self): @@ -409,6 +409,7 @@ class SOS_IR_Line_Material(models.Model): unit_price = fields.Monetary(string="Unit Price", currency_field='currency_id') test_report = fields.Binary(string="Test Report") test_report_filename=fields.Char(string="Test Report File Name") + expiry_date = fields.Date(string="Expiry Date") @api.onchange('component_id') def _onchange_component_id(self): if self.component_id: diff --git a/sos_inventory/models/sos_material.py b/sos_inventory/models/sos_material.py index 9ea2156..732b187 100755 --- a/sos_inventory/models/sos_material.py +++ b/sos_inventory/models/sos_material.py @@ -48,6 +48,8 @@ class SOS_Material(models.Model): string="Materials History - In", domain=[('action', '=', 'in')] ) + + shelf_life = fields.Selection([('yes', 'Yes'), ('no', 'No')],default="no", string="Shelf Life",required=True) line_ids_out = fields.One2many( 'sos_material_transaction_history', 'ref_id', diff --git a/sos_inventory/models/sos_mon.py b/sos_inventory/models/sos_mon.py index 8b30f09..29e8f49 100755 --- a/sos_inventory/models/sos_mon.py +++ b/sos_inventory/models/sos_mon.py @@ -14,7 +14,7 @@ class sos__mon(models.Model): mon_date = fields.Date(string="MON/SON/FON Date", required=True, default=fields.Date.today) min_no = fields.Many2one('sos_min',string="MIN/SIN/FIN No") filled_by = fields.Many2one('res.users', string='Filled By', readonly=True,required=True,default=lambda self: self.env.user) - logged_inuser_group=fields.Boolean(string='Group Name',compute='compute_user_grp') + logged_inuser_group=fields.Boolean(string='Group Name',compute='compute_user_grp',store=True) dept = fields.Many2one('sos_departments',string="Department") purpose = fields.Char(string="Purpose") product_name = fields.Many2one('sos_fg', string='Material/Product Name & No') @@ -61,7 +61,7 @@ class sos__mon(models.Model): auto_load_fg_item_ids = fields.Many2many( 'sos_fg', compute='_compute_fg_items', - store=False + store=True ) company_id = fields.Many2one('res.company', store=True, copy=False, string="Company", @@ -70,7 +70,7 @@ class sos__mon(models.Model): related='company_id.currency_id', default=lambda self: self.env.user.company_id.currency_id.id) - approx_value = fields.Monetary(compute='_compute_approx_value', string="Approximate Value", currency_field='currency_id', readonly=True) + approx_value = fields.Monetary(compute='_compute_approx_value', string="Approximate Value", currency_field='currency_id', readonly=True,store=True) status = fields.Selection([ ('open', 'Open'),('close', 'Closed')], default='open' , string="Status") active = fields.Boolean(default=True) @api.constrains('indent_ref_no', 'auto_load_fg_items') @@ -189,6 +189,8 @@ class sos__mon(models.Model): @api.onchange('auto_load_fg_items') def _onchange_auto_load_fg_items(self): + if not self.auto_load_fg_items: + return if self.auto_load_fg_items: self.material_option = True self.sfg_option = True diff --git a/sos_inventory/models/sos_mrn.py b/sos_inventory/models/sos_mrn.py index e4835bf..756d2b2 100755 --- a/sos_inventory/models/sos_mrn.py +++ b/sos_inventory/models/sos_mrn.py @@ -46,7 +46,51 @@ class sos__mrn(models.Model): default=lambda self: self.env.user.company_id.currency_id.id) approx_value = fields.Monetary(compute='_compute_approx_value', string="Approximate Value", currency_field='currency_id', readonly=True) - + @api.onchange('min_no') + def _onchange_min_no(self): + if self.min_no: + self.material_option = self.min_no.material_option + self.sfg_option = self.min_no.sfg_option + self.fg_option = self.min_no.fg_option + #materials + self.line_ids_material = [(5, 0, 0)] + material_lines = [] + for material in self.min_no.line_ids_material: + line_vals = { + 'mrn_id': self.id, + 'component_id': material.component_id, + 'qp_no': material.qp_no, + 'uom': material.uom, + 'quantity': material.quantity + } + material_lines.append((0, 0, line_vals)) + + self.line_ids_material = material_lines + #sfg + self.line_ids_sfg = [(5, 0, 0)] + sfg_lines = [] + for sfg in self.min_no.line_ids_sfg: + line_vals_sfg = { + 'mrn_id': self.id, + 'component_id': sfg.component_id, + 'qp_no': sfg.qp_no, + 'quantity': sfg.quantity + } + sfg_lines.append((0, 0, line_vals_sfg)) + + self.line_ids_sfg = sfg_lines + #sfg + self.line_ids_fg = [(5, 0, 0)] + fg_lines = [] + for fg in self.min_no.line_ids_fg: + line_vals_fg = { + 'mrn_id': self.id, + 'component_id': fg.component_id, + 'quantity': fg.quantity + } + fg_lines.append((0, 0, line_vals_fg)) + + self.line_ids_fg = fg_lines @api.depends('line_ids_material.total_cost') def _compute_approx_value(self): for record in self: @@ -115,6 +159,7 @@ class sos__mrn(models.Model): def action_report_esign_btn1(self): sequence_util = self.env['sos_common_scripts'] splitted=self.order_type.split(",") + customer_return_record = False if self.return_type == "customer": sequence_util = self.env['sos_common_scripts'] tc_no = sequence_util.generate_sequence('sos_transfer_challan_return_from_customer','TC', 'tc_no') diff --git a/sos_inventory/models/sos_ncmr.py b/sos_inventory/models/sos_ncmr.py index 791c9e1..45aff0e 100755 --- a/sos_inventory/models/sos_ncmr.py +++ b/sos_inventory/models/sos_ncmr.py @@ -56,6 +56,7 @@ class NCMR_Model(models.Model): comments_on_capa = fields.Html(string="Comments on Corrective / Preventive Action ") qa_comments=fields.Text(string="QA Comments") qa_done_on = fields.Date(string="Verified On") + rework_responsible_rd_user = fields.Many2one('res.users',string='R&D User') rd_user = fields.Many2many('res.users',string='R&D User', relation='sos_ncmr_rd_user_rel') qa_by = fields.Many2one('res.users',string='QC In-Charge',readonly=True) qa_sign = fields.Image(related="qa_by.signature_image",string='QC In-Charge',readonly=True) @@ -94,10 +95,15 @@ class NCMR_Model(models.Model): string="Rework Action", default="inhouse" ) + rework_action_by_qc = fields.Boolean(string="Rework") rd_comments=fields.Text(string="Comments") rd_approval_by = fields.Many2one('res.users',string='R&D In-Charge',readonly=True) rd_approval_sign = fields.Image(related="rd_approval_by.signature_image",string='R&D In-Charge',readonly=True) rd_approval_on = fields.Datetime(string="Approved On") + rework_rd_approval_by = fields.Many2one('res.users',string='Rework - R&D In-Charge',readonly=True) + rework_rd_approval_sign = fields.Image(related="rework_rd_approval_by.signature_image",string='Rework - R&D In-Charge',readonly=True) + rework_rd_approval_on = fields.Datetime(string="Approved On") + combined_incoming_doc_ref = fields.Reference( selection=[ ('sos_iqi', 'IQI Ref No'), @@ -244,7 +250,8 @@ class NCMR_Model(models.Model): open_count = sum(1 for rec in line.defective_status_ids if rec.status == 'open') closed_count = sum(1 for rec in line.defective_status_ids if rec.status == 'closed') - closure_rate = ((closed_count/required_ncmr)*100) + closure_rate = (closed_count / required_ncmr) * 100 if required_ncmr else 0.0 + ppm = None @@ -668,6 +675,13 @@ class NCMR_Model(models.Model): 'rd_approval_by', 'rd_approval_on' ) + def action_rework_rd_esign_btn(self): + send_email = self.env['sos_common_scripts'] + send_email.action_assign_signature( + self, + 'rework_rd_approval_by', + 'rework_rd_approval_on' + ) def action_qa_esign_btn(self): if self.action_group: @@ -678,6 +692,20 @@ class NCMR_Model(models.Model): 'qa_tested_on', 'sos_inventory.sos_qc_user' ) + if self.rework_action_by_qc: + # Email part + body_html = f""" +

Below NCMR is waiting for your Action

+ """ + send_email = self.env['sos_common_scripts'] + send_email.send_direct_email( + self.env, + "sos_ncmr", + self.id, + self.rework_responsible_rd_user.login, + "NCMR Rework Action Request", + body_html + ) if self.action_group == "rd": # Email part body_html = f""" diff --git a/sos_inventory/models/sos_testing_parameters.py b/sos_inventory/models/sos_testing_parameters.py index 49cdd8d..02b002e 100755 --- a/sos_inventory/models/sos_testing_parameters.py +++ b/sos_inventory/models/sos_testing_parameters.py @@ -6,7 +6,7 @@ class SosTestingParameters(models.Model): _rec_name='fg_name' fg_name = fields.Many2one('sos_fg',string="FG Name") - parameter_ids = fields.One2many('sos_parameter', 'testing_id', string= 'BRR Testing Parameters',copy=True) + parameter_ids = fields.One2many('sos_parameter', 'testing_id', string= 'In-Process/BRR Testing Parameters',copy=True) fir_parameter_ids = fields.One2many('sos_parameter_fir', 'testing_id', string= 'FIR Testing Parameters',copy=True) specification_ids = fields.One2many('sos_specification', 'spec_id', string='Specifications',copy=True) deliverables_ids = fields.One2many('sos_deliverables', 'accessory_id', string='Deliverables',copy=True) diff --git a/sos_inventory/security/record_rules.xml b/sos_inventory/security/record_rules.xml index c7da269..6dce93d 100755 --- a/sos_inventory/security/record_rules.xml +++ b/sos_inventory/security/record_rules.xml @@ -44,11 +44,10 @@ - - + Sos NCMR: All Records - Read Access - [('rd_user', '=', user.id)] + [('rd_user', '=', user.id), ('rework_responsible_rd_user', '=', user.id)] diff --git a/sos_inventory/views/sos_fir_brr_view.xml b/sos_inventory/views/sos_fir_brr_view.xml index 41ddf85..bd55538 100755 --- a/sos_inventory/views/sos_fir_brr_view.xml +++ b/sos_inventory/views/sos_fir_brr_view.xml @@ -192,7 +192,7 @@ - + diff --git a/sos_inventory/views/sos_fir_view.xml b/sos_inventory/views/sos_fir_view.xml index d03c9af..f31eb38 100755 --- a/sos_inventory/views/sos_fir_view.xml +++ b/sos_inventory/views/sos_fir_view.xml @@ -119,6 +119,12 @@


+ + + +

+
+
diff --git a/sos_inventory/views/sos_ir_view.xml b/sos_inventory/views/sos_ir_view.xml index 42fdaa9..dd9cc2b 100755 --- a/sos_inventory/views/sos_ir_view.xml +++ b/sos_inventory/views/sos_ir_view.xml @@ -99,6 +99,7 @@ +