در مزارع سازمانی مایکروسافت شیرپوینت (SharePoint Server 2016 / 2019 / Subscription Edition)، بومیسازی تقویم تنها به نمایش گرافیکی روزها در فرمها محدود نمیشود. در سازمانهای دولتی، هلدینگها و دانشگاهها، بزرگترین چالش مهندسی پس از نصب تقویم شمسی، عدم هماهنگی موتور جستجوی سازمانی (Enterprise Search Service)، شکست در بازیابی اسناد بر اساس فیلترهای بازه زمانی خورشیدی، تداخل تایمر جابهای دورهای (TimerJobs) و ارسال مقادیر غیراستاندارد در وبسرویسهای REST API و CSOM است.
بستههای غیراستاندارد معمولاً با دستکاری غیراصولی لایههای دادهای یا ذخیره تاریخها به صورت رشته متنی (String)، باعث تخریب شاخصهای دیتابیس SQL Server و ناکارآمدی موتور ایندکسگذاری شیرپوینت میشوند. در مقابل، معماری بومیساز پیشرفته Licentra Jalali Suite، استانداردهای معماری مایکروسافت را کاملاً حفظ نموده و با تزریق لایههای مبدل در سطح هسته (Kernel Pipeline)، هماهنگی ۱۰۰٪ با موتور جستجوی سازمانی و فراخوانیهای سرویسهای خارجی را تضمین میکند.
۱. معماری موتور جستجوی سازمانی (Enterprise Search) با فیلدهای تاریخ شمسی #
موتور جستجوی شیرپوینت اسناد را از طریق پردازشگر محتوا (Content Processing Component) بررسی کرده و فرادادههای تاریخ را به صورت ویژگیهای خزیده (Crawled Properties) استخراج میکند. این ویژگیها سپس به ویژگیهای مدیریتشده (Managed Properties) نگاشت میشوند:
┌────────────────────────────────────────────────────────┐
│ اسناد، نامهها و آیتمهای شیرپوینت │
│ [فیلد تاریخ نامه: ۱۴۰۴/۱۲/۱۰] (ذخیره استاندارد UTC) │
└──────────────────────────┬─────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────┐
│ خزنده محتوا (Search Crawler Component) │
│ - استخراج ویژگی تاریخ: ows_LetterDate (Crawled Prop) │
└──────────────────────────┬─────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────┐
│ پردازشگر محتوا و بومیساز Licentra Jalali Suite │
│ - نرمالسازی تاریخ خورشیدی به فرمت استاندارد ایندکس │
│ - نگاشت به Managed Property با قابلیت RefinableDate │
└──────────────────────────┬─────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────┐
│ شاخص جستجو (Search Index) │
│ - قابلیت پالایش در کادر فیلتر جستجو (Search Refiner) │
│ - پشتیبانی از عبارات کوئری زبان KQL با بازه خورشیدی │
└────────────────────────────────────────────────────────┘
۲. جدول مقایسه رفتار سیستم در سناریوهای بومیسازی تقویم #
برای انتخاب راهکار اصولی، جدول زیر تفاوتهای میان روشهای سطحی و راهکار اصولی لایسنترا را در لایههای مختلف نشان میدهد:
| لایه عملکردی فارم شیرپوینت | روشهای غیراستاندارد (اسکریپت سطحی) | راهکار هستهای مهندسی Licentra |
|---|---|---|
| ذخیرهسازی در SQL Server | ذخیره به صورت متن شمسی (خرابی شاخصهای دیتابیس) | ذخیره کامپایلشده DateTime استاندارد بر مبنای ساعت UTC |
| خزش و ایندکس محتوا (Crawl) | عدم شناسایی به عنوان فیلد تاریخ در ایندکسر | تشخیص صحیح به عنوان Datetime و امکان مرتبسازی زمانی |
| کوئریهای جستجو (KQL) | عدم امکان کوئریهای بازهای مانند >= 1404/01/01 | پشتیبانی کامل از اپراتورهای بازهای و پالایشگرهای داینامیک |
| خروجی اکسل و Power BI | تاریخ به صورت متن رشتهای صادر شده و نمودارها میشکنند | خروجی به صورت Date واقعی با قابلیت فرمتبندی جلالی در اکسل |
| تایمر جابها (TimerJobs) | جابها در زمان نامشخص متوقف شده یا همپوشانی دارند | محاسبه دقیق ساعت بر اساس گاهشماری رسمی کشوری |
| ارتباطات REST API / Webhooks | ایجاد خطاهای ۵۰۰ یا تبدیل نادرست تاریخها | تبدیل شفاف دوطرفه (UTC به جلالی و بالعکس در هدر و بدنه) |
۳. کوئریهای KQL با فیلترهای زمانی تقویم خورشیدی #
یکی از قابلیتهای کلیدی مهندسی پس از پیادهسازی صحیح، امکان جستجوی نامهها و قراردادها در کادر جستجوی پیشرفته بر اساس بازههای زمانی شمسی است:
# جستجوی نامههای صادر شده در فصل زمستان ۱۴۰۴
ContentType:"نامه اداری" AND LetterDateOWSDATE>=2026-01-20 AND LetterDateOWSDATE<=2026-03-20
# جستجوی اسناد با فیلتر پالایشگر سازمانی (Search Refinement)
IsDocument:true AND RefinableDate01>=today-30
موتور بومیساز لایسنترا در صفحه نتایج جستجو (osssearchresults.aspx)، به صورت خودکار مقادیر پالایشگرهای تاریخ (Date Refiners) را به تقویم شمسی معادلسازی کرده و به کاربر نمایش میدهد:
<!-- الگوی نمایش فیلتر تاریخ شمسی در وبپارت پالایشگر جستجو -->
<ControlTemplate>
<div class="ms-ref-refiner">
<div class="ms-ref-title">تاریخ ثبت سند (خورشیدی)</div>
<ul class="ms-ref-list">
<li><a href="?k=test&r=LetterDate%3E%3D2026-02-20">ماه جاری (اسفند ۱۴۰۴)</a></li>
<li><a href="?k=test&r=LetterDate%3E%3D2025-12-22">سه ماه اخیر (زمستان ۱۴۰۴)</a></li>
<li><a href="?k=test&r=LetterDate%3E%3D2025-03-21">سال جاری (۱۴۰۴)</a></li>
</ul>
</div>
</ControlTemplate>
۴. اسکریپت ساخت تایمر جاب استاندارد منطبق بر گاهشماری خورشیدی #
در پیادهسازی تایمر جابهای سازمانی (مانند تولید خودکار شماره نامه، آرشیو سالانه اسناد در پایان اسفند، و ارسال هشدارهای کارتابل)، تعریف زمانبندی باید مستقیماً با ساعت محلی ایران هماهنگ باشد:
using System;
using Microsoft.SharePoint.Administration;
namespace Licentra.SharePoint.Jalali.Jobs
{
public class EndOfYearArchiveJob : SPJobDefinition
{
public const string JobName = "Licentra_Jalali_EndOfYear_Archive_Job";
public EndOfYearArchiveJob() : base() { }
public EndOfYearArchiveJob(string jobName, SPService service)
: base(jobName, service, null, SPJobLockType.Job)
{
this.Title = "جاب آرشیو سالانه اسناد بر اساس تقویم خورشیدی";
}
public override void Execute(Guid targetInstanceId)
{
// دریافت زمان محلی با در نظر گرفتن مبدل رسمی گاهشماری خورشیدی
DateTime nowUtc = DateTime.UtcNow;
System.Globalization.PersianCalendar pc = new System.Globalization.PersianCalendar();
int jalaliYear = pc.GetYear(nowUtc);
int jalaliMonth = pc.GetMonth(nowUtc);
int jalaliDay = pc.GetDayOfMonth(nowUtc);
// بررسی رسیدن به آخرین روز سال خورشیدی (۲۹ یا ۳۰ اسفند)
bool isLeap = pc.IsLeapYear(jalaliYear);
int lastDayOfEsfand = isLeap ? 30 : 29;
if (jalaliMonth == 12 && jalaliDay == lastDayOfEsfand)
{
// اجرای روتین بستن دفاتر و انتقال پروندههای جاری به آرشیو راکد
ExecuteFiscalYearArchiving(jalaliYear);
}
}
private void ExecuteFiscalYearArchiving(int year)
{
// منطق آرشیو اسناد و لاگین در سیستم مانیتورینگ
}
}
}
۵. ارسال و دریافت تاریخ در REST API و CSOM #
برای سیستمهایی که از طریق اپلیکیشنهای موبایل یا پرتالهای مجزا به شیرپوینت متصل میشوند، بومیساز لایسنترا یک ماژول HTTP Handler فراهم میآورد تا کلاینتها بتوانند با تعیین هدر X-Calendar-Mode: Jalali، بدون نیاز به محاسبات سمت کلاینت، تاریخها را دریافت یا ثبت کنند:
POST /_api/web/lists/getbytitle('مکاتبات')/items HTTP/1.1
Host: sp-farm.licentra.lan
Content-Type: application/json;odata=verbose
X-Calendar-Mode: Jalali
Accept: application/json;odata=verbose
{
"__metadata": { "type": "SP.Data.LettersListItem" },
"Title": "نامه ارجاع اداری",
"LetterDate": "1404/12/15 10:30:00"
}
پایپلاین بومیساز این درخواست را قبل از ارسال به موتور ذخیرهسازی، به زمان معادل UTC برگردانده و با حفظ یکپارچگی پایگاه داده ذخیره میکند.
۶. اسکریپت استقرار خودکار و همگامسازی فارم با PowerShell #
برای نصب پکیج و تنظیم تمام وباپلیکیشنها بدون نیاز به دخالت دستی در کنسول Central Administration:
<#
.SYNOPSIS
Deploy Licentra Jalali Calendar Suite to SharePoint Farm
#>
$ErrorActionPreference = "Stop"
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
Write-Host "[DEPLOY] Installing Licentra Jalali WSP Solution..." -ForegroundColor Cyan
$wspPath = "C:\Deploy\Licentra.SharePoint.Jalali.wsp"
if (-not (Test-Path $wspPath)) {
throw "[FATAL] WSP package not found at $wspPath"
}
# Add solution to farm store
$solution = Get-SPSolution -Identity "Licentra.SharePoint.Jalali.wsp" -ErrorAction SilentlyContinue
if (-not $solution) {
Add-SPSolution -LiteralPath $wspPath
}
# Deploy globally to all GACs and Web Applications
Write-Host "[DEPLOY] Deploying solution globally with Full-Trust..." -ForegroundColor Yellow
Install-SPSolution -Identity "Licentra.SharePoint.Jalali.wsp" -GACDeployment -AllWebApplications -Force
# Verify Timer Service restart
Write-Host "[SERVICE] Restarting SharePoint Timer Service (SPTimerV4)..." -ForegroundColor Cyan
Get-Service -Name "SPTimerV4" | Restart-Service
Write-Host "[SUCCESS] Licentra Jalali Suite deployed and initialized farm-wide." -ForegroundColor Green
۷. جمعبندی و الزامات نگهداری #
استفاده از معماری استاندارد در بومیسازی تقویم شیرپوینت، ضامن پایداری سیستم در بلندمدت است. با اعمال این الگو، بهروزرسانیهای امنیتی ماهانه مایکروسافت (Cumulative Updates - CU) بدون نگرانی از تخریب فرادادهها قابل نصب خواهند بود و موتور جستجوی سازمانی با بالاترین سرعت و دقت به پاسخگویی به کوئریهای کاربران ادامه میدهد.



