• 1400/02/20

جای گذاری لایه منطق(بیزینس لاجیک) :

سلام استاد.

سوالم این هست که ما میتونیم لایه منطق رو به صورت کامل با استفاده از پروسیجرها و فانکشن ها و سایر امکانات روی خود اس کیو ال سرور پیاده سازی کنیم اینطوری سرعت پردازش به شدت بالا میره. چه دلیلی هست که این کار رو سمت اس کیو ال انجام ندیم؟ بعضی دوستان گفتن اینجوری نرم افزار به شدت به اس کیو ال یا اون دیتابیس خاص وابسته میشه، منتهی من مطمئنم که هیج وقت دیتابیسم از اس کیو ال سرور به چیز دیگه ای تغییر نمیکنه.

  • 1400/02/20
  • ساعت 22:33

البته که هنگام نوشتن برنامه مطمئنید اما اگر بخواید بعدا اون رو توسع بدید براتون مشکل ساز میشه.

اولا که قوانین s.o.l.i.d رو رعایت نکردید بعد هم اگر یک دفعه تصمیم گرفتید که از نسخه جدیدتر sql یا یک دیتابیس دیگه استفاده کنین. Business لایه ی مهمیه شاید الان فکر کنی که تا ابد نمی خوای توسع اش بدی ولی موقع توسعه چون قانون تک وظیفه ای رعایت نشده و همه متود ها و فانکشن ها یک جا تعریف شدند شما نمی تونین راحت کدتون رو توسعه بدین.

البته شما استد مایی و هر کاری که صلاحه بکن ولی این چیزایی بود می دونستم بقیه اش با شما.😊


  • 1400/02/21
  • ساعت 09:59

البته که هنگام نوشتن برنامه مطمئنید اما اگر بخواید بعدا اون رو توسع بدید براتون مشکل ساز میشه.

اولا که قوانین s.o.l.i.d رو رعایت نکردید بعد هم اگر یک دفعه تصمیم گرفتید که از نسخه جدیدتر sql یا یک دیتابیس دیگه استفاده کنین. Business لایه ی مهمیه شاید الان فکر کنی که تا ابد نمی خوای توسع اش بدی ولی موقع توسعه چون قانون تک وظیفه ای رعایت نشده و همه متود ها و فانکشن ها یک جا تعریف شدند شما نمی تونین راحت کدتون رو توسعه بدین.

البته شما استد مایی و هر کاری که صلاحه بکن ولی این چیزایی بود می دونستم بقیه اش با شما.😊

ممنون دوست خوبم از پاسخت، اما چند نکته هست:

با عوض شدن نسخه بروز اس کیو ال پروسیجرها و فانکشن‌ها تغییر نمیکنن.

اینکه میفرمایید همه متدها و فانکشن‌ها یک جا تعریف شدند تا حدی درسته اما میتونیم با استفاده از اسکیما اون‌ها رو دسته بندی کنیم یا حتی با اسم گذاری دقیق. مثلا Sp_Ins همیشه برای اینزرت استفاده میشه و بعد از این عبارت اسم جدولش میاد مثلا  sp ins Person. برای استفاده از اسکیما هم میتونیم بخش‎‌های مختلف نرم افزار رو از هم تفکیک کنیم مثلا برای نوشتن یک نرم افزار حسابداری ما یک سری موجودیت‌های پایه داریم مثل اشخاص، کالا، انبار، واحد، بانک و ...

این‌ها رو میتونیم در یک اسکیما به اسم Base دسته بندی کنیم. بخش بعدی شامل تراکنش ها میشه مثل حواله و چک و ... اون ها رو هم داخل یک اسکیما دسته بندی می‌کنیم. اینطوری هرکسی که کدهای ما رو ببینه نظم رو درک میکنه.

طبعیتاّ دسته بندی کدها مثل سی شارپ نمیشه که کلاس داشته باشه ولی باز هم میتونیم منظم کار کنیم.

مزیت اصلی این شیوه سرعت بالای پردازش هست. پروسیجرها از قبل کمپایل میشن و وقتی فراخوانی صورت میگیره خیلی سریع انجام میشه. این مزیت در برنامه نویسی شبکه خیلی کمک میکنه.

 

بحث توسعه شد، توسعه کدهای اس کیو ال هم خیلی ساده تر از توسعه کدهای نرم افزاره. شما میتونید  اون پروسیجرتون رو به سادگی ویرایش کنید و به نرم افزارتون دست نزنید. نیازی به بارگذاری مجدد نسخه جدید نرم افزار برای مشتریان نیست. فقط یه اسکریپت T-SQL بارگذاری میشه.

درواقع در این حالت نرم افزاری که ما مینویسیم خیلی شبیه میشه به SQL Management Studio. کاربر فقط تعیین میکنه که چیکار میخواد بکنه و نرم افزار هم فقط پروسیجر رو صدا میزنه. از هیچ چیز دیگه ای خبر نداره. در این حالت نرم افزار شامل دو قسمت میشه: لایه اینترفیس، لایه دیتااکسز.


  • 1400/02/21
  • ساعت 21:56

بله حق با شماست ولی اگه بانکتون از sql به no sql تغییر کرد چی؟ ممکنه بخوایم ul اپلیکیشن یا سایتمون رو تغییر بدیم

اینجوری کار ما سخت می شه و ممکنه تمام اپ ریزش می کنه. ممکنه بخوایم یک قابلیت جدید به سایت اضافه کنیم. سیستم احراز هویتمون رو تغییر بدیم ، به خاطر وابستگی لایه ها و خبر داشتن لایه ها از هم اپمون ریزش می کنه.  

 البته حرف شما کاملا درسته. برای کاری که شما میگین که انبار یه لایه جدا، محصولات یه لایه جدا باشه.

به این دوره سر بزنین، معماری خیلی جالبیه. شبیه همون چیزیه که شما می خواین. البته اگه منظورتون رو درست فهمیده باشم.

آموزش Micro Service ها در Core (toplearn.com)

 


  • 1400/02/22
  • ساعت 09:12

بله حق با شماست ولی اگه بانکتون از sql به no sql تغییر کرد چی؟ ممکنه بخوایم ul اپلیکیشن یا سایتمون رو تغییر بدیم

اینجوری کار ما سخت می شه و ممکنه تمام اپ ریزش می کنه. ممکنه بخوایم یک قابلیت جدید به سایت اضافه کنیم. سیستم احراز هویتمون رو تغییر بدیم ، به خاطر وابستگی لایه ها و خبر داشتن لایه ها از هم اپمون ریزش می کنه.  

 البته حرف شما کاملا درسته. برای کاری که شما میگین که انبار یه لایه جدا، محصولات یه لایه جدا باشه.

به این دوره سر بزنین، معماری خیلی جالبیه. شبیه همون چیزیه که شما می خواین. البته اگه منظورتون رو درست فهمیده باشم.

آموزش Micro Service ها در Core (toplearn.com)

سلام.

من یقین دارم که هیچ وقت دیتابیسم از Ms Sql Server به چیز دیگه‌ای تغییر نمیکنه. سال هاست دارم با همین دیتابیس کار میکنم و به صورت جامع همه نیازهای مشتریان رو برطرف کرده.

شما اگر بخواید لایه UI رو تغییر بدید که نیازی به دست کاری کد اس کیو ال ندارید. این در هیچ معماری پذیرفته نیست.

معماری که گفتم به این شکل هست که شما منطق کسب و کار رو روی اس کیو ال پیاده سازی میکنید به جای این که کلاس بسازید داخل سی شارپ. فرضاً برای یک نرم افزاری حسابداری کاربر وقتی داره شخص تعریف میکنه همونجا باید مطرح کنه که این شخص چه رابطه ای با شرکت داره؟ بدهکاره یا بستانکار؟ وقتی شخص داخل جدول خودش اینزرت میشه، یک سطر هم داخل جدول حساب اشخاص باید اینزرت بشه تحت عنوان اول دوره. این رابطه ها رو ما توی اس کیو ال مطرح میکنیم. داخل نرم افزار، سی شارپ فقط یک پروسیجر به اسم SP Ins Person رو میشناسه و از هیچ چیز دیگه ای خبر نداره. میگه اقا من میخوام یه شخص ثبت کنم. بقیه رابطه ها رو اس کیو ال هندل میکنه. نرم افزار نیازی نداره بدونه یک جدول دیگه هم هست به اسم حساب اشخاص که اونجا هم باید یک ریکورد ثبت کنم. این یک مثال خیلی کوچیک بود.

شما اگر کمی رابطه هاتون زیادتر یا پیچیده تر بشه این روش کارآمد بودن خودش رو بیشتر ثابت میکنه. فرض کنید یک جدول با سه تا جدول دیگه رابطه داره و حداقل سه عملیات اینزرت، آپدیت، دیلیت روی جدول اول امکان پذیره.

اگر بخواید این رو در سی شارپ پیاده سازی کنید مدام باید کانکشن رو باز کنید، عملیات رو انجام بدید، ببندید. جدای از این، کدتون باید داخل اس کیو ال کمپایل بشه. این ها زمان بر هستن.

 

در معماری N-Tier شما چندلایه باید در سی شارپ بسازید: 1. دیتااکسز 2. بیزینس لاجیک 3.یوآی 4.مدل

معماری که من گفتم فقط لایه بیزینس رو میبره روی اس کیو ال سرور. 

 

در ویکی پدیا اگر درباره بیزینس لاجیک بخونید گفته شده بیزینس لاجیک مکان خاصی نداره، هرجایی میتونه باشه.

درست هم هست. بیزینس لاجیک حتی در یوآی هم مطرح میشه. بر اساس منطق کسب و کار یوآی طراحی میشه.

بر اساس منطق کسب و کار جداول طراحی میشه. این ها رو نمیتونیم کاری کنیم. جدایی منطق از لایه های دیگه غیر ممکنه. شما فرض بفرمایید که برای Validation، اعتبارسنجی ها به سبکی هست که منطق کسب و کار رو نقض نکنه. حالا این اعتبارسنجی هرجا که پیاده سازی بشه بخشی از منطقه.

شما حتی اگه با این معماری که من گفتم هم کار نکنید باز هم تا حدی درگیرش هستید. وقتی داخل یک جدول کلید خارجی(Foreign Key) تعریف میکنید در واقع این یک منطقه. منطقش به این شکله که این جدول در این ستونش نباید هیچ مقداری رو بگیره که کلید اصلی جدول دیگر نباشه. میشه یک محدودیت(Constraint). در واقع شما به اس کیو ال سرور گفتید که حواست باشه این ستون این منطق رو داشته باشه و هیچ وقت نقض نشه. چون منطق کسب و کار این شکلیه که هر زیرفاکتور قطعاً متعلق به یک فاکتوره. زیرفاکتور بدون فاکتور نباید داشته باشیم. این خودش منطقه.

منطق همه جا هست و تفکیک منطق به صورت کامل محاله. طبیعی هم هست.

فقط باید حواسمون به کمیت این قضیه باشه. کدی که منطق داره نباید داخل یوآی و Code Behind پیاده سازی بشه ترجیحاً. حتی این هم بعضی وقتا نقض میشه. ولیدیشن ها بعضی وقتا نیاز هست در کدبیهایند صورت بگیره(پلتفرمی مثل وین فرم).

 

به نظر من باید سعی بشه هیچ وقت ماهیت دیتابیس رو عوض نکنیم. از ابتدا باید تشخیص بدیم این سایت چه دیتابیسی براش مناسبه. قطعاً کسب و کارهای بزرگ مثل اینستاگرام نباید از اس کیو ال سرور استفاده کنن.

شما اگر دیتابیستون رو از اس کیو ال بخواید ببرید سمت نو اس کیو ال وارد دنیایی از مشکلات میشید. مشکل هاست.

مشکل تغییر کد فراوان. مشکل زمان. حتی الامکان باید سعی بشه این اتفاق نیوفته. من خودم داخل نرم افزارهایی که ساختم کلاس های سرویسم به صورت استاتیک هست و از الگوی ریپوزیتوری استفاده نمیکنم. دلیلی نداره تغییر بخواد در یک سطح انقدر عمیق صورت بگیره. که شما بیای دیتااکسز رو داینامیک بسازی. یه وقت یک بحثی مطرحه مثل استفاده از SMTP. خب اینجا خیلی کار درستیه که داینامیک باشه. هرلحظه امکان تحریم هست. اینجا باید بشه با کمترین تغییر کد سرویس دهنده رو عوض کرد. حتی بدون تغییر کد و کاملاً اتومات. این زیبایی برنامه نویسیه واقعاً. اما به نظر من تغییر یک مدیریت کننده دیتابیس خیلی تصمیم عجیبیه. مثل اینه شما بخوای برنامه رو که با سی شارپ نوشتی با پایتون بنویسی. این خیلی عجیبه. شاید واقعاً در سطح نرم افزارای خیلی خیلی بالا به این مشکل برخوردن. ولی حقیقتاً من در دوره کاری ام ندیدم تاحالا کسی این کارو بکنه.

 

باز هم تشکر میکنم از شما که شرکت میکنی در بحث. دوست دارم همینطوری ادامه بدیم تا به نتیجه ای برسیم.

شرمنده طولانی میشه دوست دارم قشنگ بپردازیم به نکات ریز این قضیه.

 

اون دوره میکروسرویس رو هم چشم نگاه میکنم. ممنون.

 


  • 1400/02/22
  • ساعت 18:09

خواهش می کنم. وظیفه است. 

البته که کار سختیه لایه بندی ولی به تصویر پایین یک نگاه بکن نمونه ای از کار کثیف که همه چی تو همه و از ریپوزیتوری هم استفاده نشده اگر حتی موقع نوشتن کد به یک ارور بر بخوره کل برنامه درگیر میشه که شد و ارور تا حدی پیش رفت که روی کد های وین فرم هم به ارور بر خوردم چون لایه ها وابسته بودند و هر جا رو درست می کردی جای دیگش به ارور می خورد. بعضی اوقات ممکن لایه بندی ساعت ها طول بکشه ولی در عوض هندل ارور ها خیلی ساده تر میشه. فرض کنین یک ارور ساده موقع جا به جایی دیتا روی کل برنامه اثر بذاره. به نظر من اگه از معماری استفاده کنین هزینه هایی مثل دوباره نویسی بخش زیادی از برنامه نمی شین. لایه بندی کد علاوه بر توسعه کار ما رو برای سرعت کار هم مفید.

بعد هم اگه یک دفعه مشتری خواست که برنامشو توسعه بدی نباید بتونی؟ تازه اگه شما نتونی و مشتری به یک نفر دیگه سپرد کد تمیزی نوشتی که خوانایی داشته باشه؟ البته که زیبایی کد هم خیلی مهمه. اگه مثلا خواستی یک اپ خودت بنویسی برای خودت اونجا دیگه باید بتونی توسعه اش بدی. یا اگه تو تیم کار می کنی باید بقیه هم بتونن کدت رو بخونن پس زیبایی هم مهمه. البته اگه امتحان کردینو درست کار کرده باز هم می تونین ازش استفاده کنین.

خوشحال میشم ما رو در گیت ها هم دنبال کنید. ;) DanialFaezian

 

 


  • 1400/02/24
  • ساعت 14:22

چه خبر دوست عزیز به نتیجه رسیدین؟


  • 1400/02/26
  • ساعت 09:57

البته که کار سختیه لایه بندی ولی به تصویر پایین یک نگاه بکن نمونه ای از کار کثیف که همه چی تو همه و از ریپوزیتوری هم استفاده نشده اگر حتی موقع نوشتن کد به یک ارور بر بخوره کل برنامه درگیر میشه که شد و ارور تا حدی پیش رفت که روی کد های وین فرم هم به ارور بر خوردم چون لایه ها وابسته بودند و هر جا رو درست می کردی جای دیگش به ارور می خورد. بعضی اوقات ممکن لایه بندی ساعت ها طول بکشه ولی در عوض هندل ارور ها خیلی ساده تر میشه. فرض کنین یک ارور ساده موقع جا به جایی دیتا روی کل برنامه اثر بذاره. به نظر من اگه از معماری استفاده کنین هزینه هایی مثل دوباره نویسی بخش زیادی از برنامه نمی شین. لایه بندی کد علاوه بر توسعه کار ما رو برای سرعت کار هم مفید.

سلام دوست خوبم.

عکسی که فرستادید رو نگاه کردم. به هیچ عنوان این شکلی کد زدن رو نمیپسندم و مدافع سرسخت لایه بندی هستم.

کدها باید دسته بندی بشن. کد باید صریح باشه. هیچ جای ابهامی نمونه. از روی اسامی بشه به سرعت فهمید این کد میخواد چیکار کنه. من این رو قبول دارم. همینطور برای لایه بندی. لایه بندی هم باید صراحت داشته باشه. یک بار که داکیومنت پروژه رو میخونیم بدونیم دقیقاً این لایه چیا رو در بر میگیره. اگه یک خط کد بی ربط در این لایه دیدیم باید تعجب کنیم.

درباره الگوی ریپوزیتوری، من با این شیوه ارتباط نمیگیرم. به نظر من امکان اینکه بخوایم ORM یا دیتابیس رو عوض کنیم چیزی در حد صفره. دلیلی برای استفاده از ریپوزیتوری نیست. داینامیک کردن لایه دیتا کارایی نداره. اینکه من بیام به تعداد سرویس هام اینترفیس تعریف کنم کار وقت گیر و بلااستفاده است. میدونم که نرم افزار قراره با این اینترفیس کار کنه و فقط یک جا تعریف میکنیم که نحوه پیاده سازی این اینترفیس برعهده کدوم کلاسه (تکنولوژی‌هایی مثل نینجکس). اما واقعاً چقدر نیازه این کار؟ اینکه بقیه با همین فرمون رفتن جلو دلیل قانع کننده‌ای نیست. کد باید زیبا باشه. بدون حتی یک خط اضافه. استفاده درست از اینترفیس جایی هست که جا به جایی بین تکنولوژی ها زیاده. مثل وقتی که بعضی وقتا باید برای اعلان چیزی SMS بفرستیم و بعضی وقتا ایمیل. یک اینترفیس مثلاً به اسم ارسال پیغام درست میکنیم با یک متد Send که اطلاعات مبدا، مقصد و پیغام رو ورودی میگیره. دو کلاس ارسال با اس ام اس و ارسال با ایمیل از این اینترفیس ارث بری میکنن و نسبت به شرایطمون میتونیم از هر پیاده سازی استفاده کنیم. یا مثلاً برای استفاده از تکنیکی مثل پلاگین. اینجا اینترفیس کارایی داره. اما درباره ریپوزیتوری این شکلی نیست.

 

و درباره بحث خودمون.

من هم لایه بندی رو استفاده میکنم اما نه به شیوه ای که تدریس میشه توی دوره ها. من از پذیرفتن مباحث آکادمیک که دلیلی براشون نباشه بیزارم :)). به این تصاویر نگاه کنید:

عکس اول لایه بندی من در سی شارپه.

یک لایه برای ارتباط با دیتابیس تحت عنوان DAL. کلاس هاش استاتیک هستن.

یک لایه به اسم Entity که همون مدل هست. موجودیت هام داخل این لایه است. بعضی موجودیت ها با پیشوند View نوشته شدن. اون ها موجودیت های ادغام شده هستن که کاربر نیاز داره. مثلاً هروقت اطلاعات شخصی رو میخواد باید ببینه موجودی مالیش چقدره. موجودی مالی از جدول دیگه میاد اما باید با همین اشخاص Join بشه. این جور موجودیت ها رو به اسم View_Ent تعریف کردم. روش رایجی هم هست. اونایی که MVC کار میکنن با این موارد برخورد داشتن.

یک لایه به اسم ابزار. ابزارایی مثل تبدیل تاریخ رو داخل این قرار میدم. 

یک لایه هم به اسم ویو که کاربر میبینه. این لایه یک بخشی داره به اسم فیلتر. که کاربر  انتخاب میکنه اطلاعات رو چجوری ببینه.

لایه بیزینس لاجیک ندارم چون در دیتابیس پیاده سازی شده.

عکس دوم یک نمونه کد از لایه DAL هست.

عکس سوم هم لایه منطق در دیتابیسه. البته من با اسکیما دسته بندی نکردم. یعنی باید یه اسکیما به اسم Base درست کنم که در موجودیت هایی که تعاریف اولیه هستند(مثل اشخاص، بانک، کالا، واحد و ...) به جای dbo از اون استفاده بشه.

در پاسخ بعدی یک نمونه کد از این پروسیجرها رو قرار میدم.


  • 1400/02/26
  • ساعت 10:12

در پاسخ بعدی یک نمونه کد از این پروسیجرها رو قرار میدم.

کد ها یجورین اگه عکس بگیرم در یک قاب جا نمیشن. متنش رو میفرستم:

این یک متد(پروسیجر) هست که میخواد شخص رو اینزرت کنه.

وقتی شخصی در نرم افزار تعریف میشه کاربر باید مشخص کنه در همین ابتدا این شخص چه رابطه ای با شرکت داره؟  آیا بدهکاره یا بستنکار یا بی حساب؟ این ها هم باید در جدول حساب شخص ثبت بشه، یعنی یک ریکورد تحت عنوان اول دوره(First Amount) که به صورت مخفف FA نوشته میشه ثبت خواهد شد.

یک متغیر داره برای اینکه آیدی این شخصی که اینزرت میکنیم رو بگیریم و در جدول حساب اشخاص از همین استفاده کنیم. بعد از اینتزرت شخص میریم سراغ اینزرت حسابش برای اول دوره و پروسیجر اینزرت همون جدول رو صدا میزنیم. اینجا فقط پارامتر تاریخ اول دوره رو nvarchar  گذاشته بودیم که تغییر میدیم به DateTime.

این یک پروسیجر ساده هست و اونقدر پیچیدگی نداره. اما وابستگی چرا. به دوتا جدول وابسته است. پیاده سازی همین متد داخل سی شارپ هم امکان پذیره. یک لایه(پروژه) به اسم BLL یا Business Logic Layer درست کنیم یک کلاس برای اشخاص. در متد اینزرت این کلاس، اینزرت جدول اشخاص و اینزرت جدول حساب اشخاص رو صدا میزنیم. لایه ویو(همون لایه ای که کاربر میبینه) ارتباطش با لایه دیتابیس از طریق لایه BLL خواهد بود و به هیچ وجه به صورت مستقیم ارتباط برقرار نخواهد کرد. اما اگر بخوایم این شکلی در سی شارپ کار کنیم معایبی داره. به ازای هر اینزرت کانکشن باز و بسته میشه. یعنی برای همین متد باید دوبار کانکشن باز بشه و بسته بشه. اون هم به شرط اینکه وقتی شخص رو اینزرت میکنید آیدیش رو با همون کوئری برگردونید. اگه این کارو نکنید باید سه بار کانکشن رو باز کنید. دوم اینکه کد اینزرتمون باید روی اس کیو ال کامپایل بشه. این ها زمان بر هستن. استفاده از پروسیجر به شکلیه که از قبل کامپایل شده خواهد بود و فقط کافیه یه بار کانکشن رو باز کنید و صداش بزنید. تمام منطق رو خودش انجام میده. هزارتا اینزرت هم نیاز باشه انجام بشه خودش انجام میده و دیگه در نرم افزار خبری از این جزئیات نیست. توسعه راحتی هم داره. پروسیجر رو باز میکنید، ادیت میکنید، و کامپایل میکنید. بدون دست زدن به کد نرم افزار و بیلد کردن دوباره، نحوه انجام عوض میشه.

ALTER procedure [dbo].[Sp_Ins_Person](
                              @Code char(3),
                              @Name nvarchar(50),
                              @Telephone nvarchar(30),
                              @Phone1 nvarchar(30),
                              @Phone2 nvarchar(30),
                              @Address nvarchar(300),
                              @Card_Number nvarchar(30),
                              @Account_Number nvarchar(30),
                              @SHABA_Number nvarchar(50),
                              @Detail nvarchar(50),
                              @FirstAmount money,
                              @FirstAmountDate char(19),
                              @FirstAmountNature nvarchar(10)
                              )
AS
Begin

SET NoCount On;

Declare @LastPersonId integer = 0

Insert Into Tbl_Person (Code,
                        Name,
                        Telephone,
                        Phone1,
                        phone2,
                        Address,
                        Card_Number,
                        Account_Number,
                        SHABA_Number,
                        Detail,
                        Account_Balance,
                        Account_Balance_Nature
                        )
                        Values(
                              @Code,
                              @Name,
                              @Telephone,
                              @Phone1,
                              @Phone2,
                              @Address,
                              @Card_Number,
                              @Account_Number,
                              @SHABA_Number,
                              @Detail,
                              @FirstAmount,
                              @FirstAmountNature
                              );
                              
SET @LastPersonId = (Select IDENT_CURRENT('Tbl_Person'));                       
                              
Exec Sp_Ins_PersonTurnOver 
@PersonId = @LastPersonId,
@Date = @FirstAmountDate,
@DocType = 'FA',
@DocNumber = @LastPersonId,
@Amount = @FirstAmount,
@Nature = @FirstAmountNature;
                           
                          
End

logo-samandehi