Merge branch 'paritosh-main1' of http://git.wdipl.com/Mayank.Mishra/MinglarBackendNestJS into mayankSprint2
This commit is contained in:
357
src/common/utils/constants/agreementTemplate.ts
Normal file
357
src/common/utils/constants/agreementTemplate.ts
Normal file
@@ -0,0 +1,357 @@
|
||||
export const AGREEMENT_TEMPLATE = `
|
||||
MINGLAR HOST AGREEMENT
|
||||
Effective Date: [EFFECTIVE_DATE]
|
||||
|
||||
BETWEEN
|
||||
|
||||
Minglar India Private Limited, a company incorporated under the Companies Act, 2013, having its registered office at 602, Aaradhya Avenue X Eve, Naidu Colony, Pant Nagar, Ghatkopar (East), Mumbai 400075 (hereinafter referred to as “Minglar India Private Limited”, which expression shall include its successors and permitted assigns);
|
||||
|
||||
AND
|
||||
|
||||
[HOST_LEGAL_NAME], a [COMPANY_TYPE], having its principal place of business at [FULL_ADDRESS] (hereinafter referred to as “Host”, which expression shall include its owners, partners, directors, employees, representatives, and permitted assigns).
|
||||
|
||||
Minglar India Private Limited and Host are individually referred to as a “Party” and collectively as the “Parties”.
|
||||
|
||||
1. PURPOSE AND RELATIONSHIP
|
||||
|
||||
1.1 Platform Overview
|
||||
Minglar India Private Limited operates a curated digital marketplace under the brand “Minglar” that enables users (“Users”) to discover, review, and book experiential activities, events, workshops, tours, and related services (“Activities”) offered by independent Hosts.
|
||||
|
||||
1.2 Engagement
|
||||
The Host desires to list and provide its Activities on the Minglar platform subject to the terms and standards set forth in this Agreement.
|
||||
|
||||
1.3 Independent Contractor
|
||||
Nothing in this Agreement shall be construed as creating a partnership under the Indian Partnership Act, 1932, joint venture, agency, employment, franchise, or profit-sharing arrangement. The Host operates strictly as an independent contractor and shall have full operational control over execution of its Activities.
|
||||
|
||||
2. TERM
|
||||
|
||||
2.1 Duration
|
||||
This Agreement shall remain valid for a fixed term of [DURATION_TEXT] and shall automatically expire on [EXPIRY_DATE], unless terminated earlier in accordance with Section 16.
|
||||
|
||||
2.2 Renewal
|
||||
Renewal shall be subject to mutual agreement. Commission adjustments, if any, shall apply only at renewal due to inflation or additional expenses incurred by Minglar India Private Limited for platform upgrades or new features.
|
||||
|
||||
3. HOST RESPONSIBILITIES
|
||||
|
||||
3.1 Legal Compliance and Document Submission
|
||||
3.1.1 Compliance
|
||||
The Host shall obtain, maintain, and keep valid at all times all licenses, permits, approvals, registrations, certifications, insurance policies, and governmental permissions required under applicable laws for the lawful conduct of the Activities.
|
||||
|
||||
3.1.2 Document Upload
|
||||
The Host shall, at the time of onboarding on the Minglar platform, upload true, complete, and legible copies of licenses, permits, registrations, tax certificates (including GST registration, where applicable), identity proof, business registration documents, insurance certificates, and any other documents reasonably required by Minglar India Private Limited for verification purposes.
|
||||
|
||||
3.1.3 Accuracy and Updates
|
||||
The Host represents and warrants that all documents submitted are authentic, valid, and up to date. The Host shall promptly upload updated copies whenever any document expires, is renewed, modified, or replaced. Failure to provide valid documentation may result in suspension, delisting, or termination of this Agreement at the sole discretion of Minglar India Private Limited.
|
||||
|
||||
3.1.4 Verification
|
||||
Minglar India Private Limited shall have the right to verify such documents and request additional documentation if required for regulatory, compliance, safety, or audit purposes.
|
||||
|
||||
3.2 Accurate Listing and Host Anonymity
|
||||
3.2.1 Activity Details
|
||||
The Host shall provide complete, accurate, and up-to-date descriptions for each Activity, including inclusions, exclusions, duration, safety requirements, pricing, and applicable tax percentages at the time of onboarding. The Host shall ensure that all information remains current throughout the term of this Agreement.
|
||||
|
||||
3.2.2 Host Content
|
||||
Hosts retain ownership of original content they upload (such as activity descriptions, images, and videos).
|
||||
However, by uploading content, the Host grants Minglar a:
|
||||
- Worldwide
|
||||
- Non-exclusive
|
||||
- Royalty-free
|
||||
- Transferable
|
||||
- Sub-licensable
|
||||
license to use, reproduce, modify, adapt, publish, translate, distribute and display such content for purposes of operating, marketing and promoting the platform.
|
||||
This license continues for as long as the content remains on the platform.
|
||||
|
||||
3.2.3 Unique Activity Name
|
||||
The Host shall provide a unique name for each Activity during onboarding. The Host’s actual company name, personal name, or brand shall not be visible to Users on the activity card or in any public-facing listing.
|
||||
|
||||
3.2.4 Prohibition on Branding and Contact
|
||||
The Host shall not display, embed, or otherwise reveal its contact information, company name, logo, website, email, or other identifiable details in any photos, videos, descriptions, chat messages, or other content shared with Users via the Minglar platform.
|
||||
|
||||
3.2.5 Breach and Suspension
|
||||
Any attempt to circumvent these provisions or display unauthorized branding or contact details shall be considered a material breach of this Agreement. Minglar India Private Limited reserves the right to suspend or delist the Activity immediately and take other remedial actions as necessary.
|
||||
|
||||
3.3 Taxes
|
||||
3.3.1 Tax Responsibility
|
||||
The total Activity price listed shall be inclusive of all applicable taxes. Minglar India Private Limited shall collect such taxes from Users and transfer them to the Host. The Host shall be solely responsible for depositing and complying with tax obligations before local authorities.
|
||||
|
||||
4. SAFETY AND OPERATIONAL STANDARDS
|
||||
|
||||
4.1 General Duty of Care
|
||||
The Host shall conduct all Activities in a safe, hygienic, and controlled manner ensuring the well-being of Users at all times.
|
||||
|
||||
4.2 Risk Management
|
||||
The Host shall conduct risk assessments, maintain standard operating procedures, provide safety briefings, and ensure trained and competent personnel supervise Activities.
|
||||
|
||||
4.3 Transportation
|
||||
If the Host provides pick-up, drop-off, or in-Activity transportation, such transportation shall be safe, clean, reasonably comfortable, and legally compliant. The Host shall remain responsible for User safety during transport.
|
||||
|
||||
4.4 SOS Emergency Protocol
|
||||
During execution of Activities, Minglar’s SOS feature shall be active. If activated by a User, the Host Operator shall receive immediate notification and live location details. The Host Operator shall immediately contact and reach the User. The emergency shall be cleared only after ensuring the User is safe. The Host Operator shall be the first point of contact for all emergencies.
|
||||
|
||||
4.5 Equipment Standards
|
||||
The Host shall ensure that all equipment, tools, and materials used for conducting any Activity are:
|
||||
1. Maintained in accordance with the manufacturer’s recommendations and operational guidelines.
|
||||
2. Tested regularly to confirm they are safe and functional before each Activity.
|
||||
3. Kept clean, hygienic, and in good working order at all times.
|
||||
4. Adequate for the number of Users participating, ensuring no overuse or overcrowding that may compromise safety.
|
||||
The Host shall be solely responsible for any incidents, accidents, or injuries caused due to faulty, poorly maintained, unhygienic, or unsafe equipment. Failure to comply may result in suspension, delisting, or immediate termination of this Agreement under Section 16.
|
||||
|
||||
5. QUALITY AND PUNCTUALITY
|
||||
|
||||
5.1 Quality Standards
|
||||
The Host shall maintain consistently high service standards and continuously strive to improve user experience toward achieving five-star ratings.
|
||||
|
||||
5.2 Timeliness
|
||||
The Host shall ensure timely check-in, commencement, and completion of Activities. Delays impacting Users’ onward travel or other bookings shall constitute service failure.
|
||||
|
||||
6. INSURANCE
|
||||
|
||||
The Host shall obtain, maintain, and keep valid insurance coverage appropriate for the risk associated with the respective Activities. Coverage shall be sufficient to protect Users, the Host, and Minglar India Private Limited against claims arising from accidents, injuries, fatalities, or property damage.
|
||||
|
||||
6.1 Risk-Based Coverage
|
||||
The Host shall maintain Public Liability Insurance appropriate to the risk and scale of the respective Activities.
|
||||
|
||||
6.2 Coverage Amount
|
||||
For high-risk or multi-participant Activities, coverage is recommended up to INR 5 Crores or an amount appropriate to cover potential claims arising from injury, death, or property damage.
|
||||
|
||||
6.3 Additional Insured
|
||||
Policies shall name Minglar India Private Limited and Minglar Group Pte Ltd, Singapore as Additional Insured.
|
||||
|
||||
6.4 Proof
|
||||
Valid insurance certificates must be submitted prior to onboarding and maintained throughout the Agreement term.
|
||||
|
||||
7. USER WAIVERS
|
||||
The Host shall ensure that Users acknowledge and accept all standard waivers, terms, and risk disclosures prior to participation in any Activity, as provided by the Minglar platform.
|
||||
|
||||
8. INDEMNITY
|
||||
The Host shall indemnify, defend, and hold harmless Minglar India Private Limited, its affiliates, employees, directors, and representatives from any claims, losses, damages, liabilities, fines, or expenses arising directly or indirectly from the Host’s failure to comply with laws, negligence, or breach of this Agreement.
|
||||
|
||||
9. LIMITATION OF LIABILITY
|
||||
The total aggregate liability of Minglar India Private Limited arising out of or in connection with any claim relating to a specific Activity shall not exceed the total commission earned by Minglar India Private Limited from that particular Activity (or substantially similar activity category) conducted by the Host during the three (3) months immediately preceding the date of the claim.
|
||||
If the Host lists multiple different Activities, the liability cap applies only to the commission earned from the specific Activity giving rise to the claim and does not include commission earned from other unrelated Activities.
|
||||
Under no circumstances shall Minglar India Private Limited be liable for indirect, incidental, consequential, punitive, or special damages, including loss of profits, goodwill, reputation, or business opportunity.
|
||||
|
||||
10. PAYMENT AND COMMISSION
|
||||
|
||||
10.1 Commission
|
||||
10.1.1 Standard Commission
|
||||
A [COMMISSION_TEXT] commission shall be charged by Minglar India Private Limited on the Activity revenue (after deduction of applicable taxes).
|
||||
|
||||
10.1.2 Fixed During Term
|
||||
The term of this agreement is [DURATION_TEXT]. This commission shall remain unchanged during the term of this Agreement.
|
||||
|
||||
10.1.3 Renewal Adjustment
|
||||
At the time of renewal, Minglar India Private Limited reserves the right to adjust commission rates due to inflation or platform upgrades.
|
||||
|
||||
10.2 Host Payout
|
||||
10.2.1 Timing
|
||||
Minglar India Private Limited shall remit payments to the Host 24 hours after check-in completion or no-show.
|
||||
|
||||
10.2.2 Monthly Commission Invoice
|
||||
Minglar India Private Limited shall issue a monthly invoice to the Host detailing the commission earned. GST shall be charged extra.
|
||||
|
||||
10.2.3 Banking and Gateway Charges
|
||||
All banking, payment gateway, and transaction fees arising from normal bookings shall be borne by the Host.
|
||||
|
||||
11. BOOKING CANCELLATION
|
||||
|
||||
11.1 Host-Related Cancellation
|
||||
If an Activity is cancelled due to host health, extreme weather, natural disasters, government restrictions, venue issues, equipment failure, team/partner unavailability, or other uncontrollable circumstances, the Host shall pay the applicable cancellation fee charged by the payment gateway. No payment will be remitted to the Host, and 100% of the booking amount including taxes shall be refunded to Users.
|
||||
|
||||
11.2 User-Initiated Cancellation
|
||||
If Users cancel within the permitted period, the platform fee shall be deducted and the remaining amount refunded to Users. The Host will not receive payment for such cancellations.
|
||||
|
||||
12. PARTICIPATION OF MINGLAR ACCOUNT MANAGER FOR AUDIT
|
||||
In case of low performance, low bookings, or safety/quality issues reported by Users that remain unresolved for more than one week, Minglar India Private Limited may send an Account Manager to audit the Activity at the Host’s location.
|
||||
The date and slot for such an audit shall be coordinated by the Account Manager and the Host.
|
||||
The participation of the Account Manager is free of charge. If the audit requires overnight stay or the Activity duration exceeds one day, the Host shall provide accommodation.
|
||||
Transportation costs for the Account Manager shall be shared 50% by the Host.
|
||||
Minglar India Private Limited reserves the right to send an Account Manager once per year or sooner in case of low performance, safety concerns, or user complaints with less than 2-star ratings.
|
||||
|
||||
13. DATA PROTECTION, PRIVACY & INFORMATION SECURITY
|
||||
|
||||
13.1 Compliance with Applicable Laws
|
||||
The Parties acknowledge that Minglar Group Pte. Ltd. (Singapore) and/or Minglar India Private Limited (India) collects and processes personal data in compliance with applicable laws, including:
|
||||
- The Personal Data Protection Act 2012 (“PDPA”); and
|
||||
- The Digital Personal Data Protection Act 2023 (“DPDP Act”).
|
||||
Each Party agrees to comply with all applicable privacy and data protection laws in the jurisdiction where the Activity is conducted.
|
||||
|
||||
13.2 Roles of the Parties
|
||||
a) Minglar shall act as the Data Fiduciary / Data Controller for personal data collected via the Minglar platform.
|
||||
b) The Host shall act as a Data Processor / Authorized Data Recipient when processing User personal data solely for the purpose of conducting booked Activities.
|
||||
The Host shall not independently determine the purpose or means of processing User personal data without prior written authorization from Minglar.
|
||||
|
||||
PART A – USER PERSONAL DATA
|
||||
|
||||
13.3 Categories of User Data Collected
|
||||
The Host acknowledges that Minglar may collect and process the following categories of User personal data through the platform:
|
||||
a) Full name
|
||||
b) Date of birth
|
||||
c) Mobile number and email address
|
||||
d) Gender
|
||||
e) Height and weight (where Activity eligibility or safety restrictions apply)
|
||||
f) School and college information
|
||||
g) Profile photograph
|
||||
h) Home location and/or real-time GPS location
|
||||
i) Check-in and check-out data
|
||||
j) SOS or emergency alerts
|
||||
k) Payment method details and transaction information
|
||||
l) Spending preferences or monthly budget indicators
|
||||
m) Biometric verification data (including facial verification, where applicable)
|
||||
n) Medical conditions or health disclosures (Phase 2 implementation)
|
||||
o) Attendance logs and activity participation records
|
||||
|
||||
13.4 Sensitive Personal Data
|
||||
Certain categories of data may constitute sensitive personal data, including:
|
||||
- Biometric data
|
||||
- Medical or health information
|
||||
- Real-time location data
|
||||
- Financial/payment information
|
||||
- Profile photographs capable of biometric identification
|
||||
Such data shall:
|
||||
a) Be processed only where necessary for safety, verification, compliance, or Activity execution;
|
||||
b) Be accessed strictly on a need-to-know basis;
|
||||
c) Be protected using enhanced security measures;
|
||||
d) Not be downloaded, stored externally, or retained by the Host beyond the Activity duration unless legally required.
|
||||
The Host shall not independently collect additional medical, biometric, or financial data outside the Minglar platform without prior written approval.
|
||||
|
||||
13.5 Confidentiality and Use Restrictions
|
||||
The Host shall treat all User and platform data as strictly confidential, including attendance logs, SOS alerts, emergency records, and location data collected during Activities.
|
||||
User data shall:
|
||||
a) Be used solely for Activity execution and safety;
|
||||
b) Not be shared with third parties without prior written consent from Minglar India Private Limited;
|
||||
c) Not be used for independent marketing, profiling, or database creation;
|
||||
d) Not be retained after completion of the Activity unless legally required.
|
||||
The Host shall not contact Users outside the Minglar platform unless expressly authorized.
|
||||
|
||||
13.6 Security Measures
|
||||
The Host shall implement reasonable technical and organizational measures to protect personal data from unauthorized access, alteration, misuse, or disclosure, including:
|
||||
- Secure password-protected systems;
|
||||
- Restricted employee access;
|
||||
- Confidentiality undertakings from employees and operators;
|
||||
- Secure handling of operator devices used for check-in/check-out;
|
||||
- Immediate reporting of lost or compromised devices.
|
||||
|
||||
13.7 Data Breach Notification
|
||||
Any actual or suspected breach involving personal data — including medical, biometric, financial, or location data — shall be reported to Minglar India Private Limited immediately and in any event within twenty-four (24) hours of discovery.
|
||||
The Host shall fully cooperate in investigation, mitigation, and regulatory reporting obligations.
|
||||
|
||||
13.8 Retention and Deletion
|
||||
The Host shall not retain personal data beyond the period necessary for conducting the Activity unless required by law.
|
||||
Upon termination of this Agreement, the Host shall delete all User data in its possession and confirm deletion upon request.
|
||||
|
||||
13.9 User Responsibility for Medical Disclosures
|
||||
Users remain responsible for the accuracy and completeness of any medical or health information voluntarily disclosed.
|
||||
The Host may rely on such disclosures in good faith for safety and eligibility determinations.
|
||||
Minglar shall not be liable for losses arising from incomplete or inaccurate medical information provided by Users.
|
||||
|
||||
PART B – HOST PERSONAL DATA
|
||||
|
||||
13.10 Collection of Host Personal Data
|
||||
The Host acknowledges that Minglar may collect and process personal data relating to the Host and its directors, partners, employees, and authorized representatives for:
|
||||
- KYC verification and onboarding;
|
||||
- Regulatory compliance;
|
||||
- Risk assessment and fraud prevention;
|
||||
- Payment processing and settlement;
|
||||
- Audit and safety review;
|
||||
- Enforcement of this Agreement.
|
||||
|
||||
13.11 Sharing and Cross-Border Transfers
|
||||
Host personal data may be shared:
|
||||
- Within Minglar Group entities;
|
||||
- With banks, payment processors, verification agencies, insurers, auditors, and professional advisors;
|
||||
- With regulatory or governmental authorities where legally required.
|
||||
The Host acknowledges that personal data may be transferred between Singapore, India, and other jurisdictions where Minglar operates, subject to compliance with applicable cross-border transfer laws.
|
||||
|
||||
PART C – ACTIVITY LOCATION & OPERATIONAL DATA
|
||||
|
||||
13.12 Collection of Activity Location and Operational Data
|
||||
The Host agrees that Minglar may collect and process operational data relating to Activities, including:
|
||||
- Venue address;
|
||||
- Check-in and check-out locations;
|
||||
- GPS coordinates;
|
||||
- Pick-up and drop-off locations;
|
||||
- Route and logistical details;
|
||||
- Activity schedules.
|
||||
Such data may include precise geo-location information.
|
||||
|
||||
13.13 Use and Display of Location Data
|
||||
The Host expressly consents to Minglar:
|
||||
- Displaying Activity venue, pick-up, and drop-off details on the platform;
|
||||
- Using location data for navigation, safety monitoring, and emergency coordination;
|
||||
- Using such data for fraud prevention and verification.
|
||||
The Host warrants that all location data provided is accurate and lawful.
|
||||
Minglar shall not be liable for losses arising from inaccurate or misleading information provided by the Host.
|
||||
|
||||
PART D – ANALYTICS & PLATFORM OPTIMIZATION
|
||||
|
||||
13.14 Anonymized and Aggregated Data
|
||||
Minglar may use anonymized, aggregated, or de-identified data derived from User or Host activity for:
|
||||
- Platform improvement;
|
||||
- Artificial intelligence systems;
|
||||
- Recommendation engines;
|
||||
- Safety analytics;
|
||||
- Market research;
|
||||
- Business strategy and investor reporting.
|
||||
Such data shall not identify any individual User or Host.
|
||||
All analytics models, algorithms, insights, and derived data shall remain the exclusive intellectual property of Minglar.
|
||||
|
||||
PART E – LIABILITY & SURVIVAL
|
||||
|
||||
13.15 Indemnity
|
||||
The Host shall indemnify and hold harmless Minglar Group Pte. Ltd. and Minglar India Private Limited against any losses, penalties, regulatory actions, claims, damages, or costs arising from:
|
||||
- Unauthorized use of personal data;
|
||||
- Data breaches attributable to the Host;
|
||||
- Non-compliance with applicable data protection laws;
|
||||
- Inaccurate operational or location data provided by the Host.
|
||||
|
||||
13.16 Survival
|
||||
This Section 13 shall survive termination or expiry of this Agreement.
|
||||
|
||||
14. CONFIDENTIALITY
|
||||
The Host shall maintain strict confidentiality regarding all platform operations, processes, user data, and commercial information. These obligations survive five (5) years post-termination. Exceptions only apply if required by law.
|
||||
|
||||
15. NON-EXCLUSIVITY
|
||||
This Agreement does not restrict the Host from offering Activities on other platforms. Minglar India Private Limited does not claim exclusivity. The Host shall not interfere with other platform operations or solicit Users to bypass Minglar.
|
||||
|
||||
16. TERMINATION
|
||||
16.1 Immediate Termination
|
||||
Minglar India Private Limited may terminate immediately in case of breach, misrepresentation, failure to maintain safety or quality standards, or violation of this Agreement.
|
||||
16.2 Termination with Notice
|
||||
Either Party may terminate this Agreement by providing 30 days’ written notice.
|
||||
16.3 Post-Termination Obligations
|
||||
Upon termination, the Host must execute all bookings already made by Users. Minglar India Private Limited will block further bookings for the Host’s Activities.
|
||||
16.4 Commission Adjustment at Renewal
|
||||
Any change in commission shall only occur at renewal of this Agreement. No adjustments shall be made during the active term.
|
||||
16.5 Non-Exclusivity
|
||||
Termination or continuation of this Agreement does not prevent the Host from offering Activities elsewhere.
|
||||
|
||||
17. GOVERNING LAW
|
||||
This Agreement shall be governed by the laws of India. Courts at the registered office jurisdiction of Minglar India Private Limited shall have exclusive jurisdiction.
|
||||
|
||||
18. ENTIRE AGREEMENT
|
||||
This Agreement constitutes the complete understanding between the Parties and supersedes all prior communications.
|
||||
|
||||
19. HOST ACKNOWLEDGMENT & ELECTRONIC CONSENT
|
||||
19.1 Electronic Acceptance
|
||||
By clicking the “I Agree” button, the Host acknowledges they have read, understood, and accepted the terms of this Agreement and the Minglar Privacy Policy.
|
||||
19.2 Binding Agreement
|
||||
Electronic acceptance constitutes a legally binding contract, equivalent to a wet signature.
|
||||
19.3 Host Obligations
|
||||
- Provide accurate and lawful data
|
||||
- Protect User data and follow emergency protocols
|
||||
- Notify Minglar of breaches or unauthorized access
|
||||
- Comply with applicable laws
|
||||
19.4 Electronic Records
|
||||
All electronic records and communications are valid and enforceable.
|
||||
19.5 Updates
|
||||
Continued use after updates constitutes acceptance of amended terms.
|
||||
|
||||
Signed Electronically by:
|
||||
Minglar India Private Limited
|
||||
Authorized Signatory
|
||||
|
||||
Host:
|
||||
[HOST_LEGAL_NAME]
|
||||
Date: [ACCEPT_DATE]
|
||||
`;
|
||||
@@ -32,9 +32,7 @@ import AWS from 'aws-sdk';
|
||||
import dayjs from 'dayjs';
|
||||
import { toWords } from 'number-to-words';
|
||||
import { PDFDocument, StandardFonts, rgb } from 'pdf-lib';
|
||||
import { Document, Packer, Paragraph, TextRun } from 'docx';
|
||||
import PizZip from 'pizzip';
|
||||
import Docxtemplater from 'docxtemplater';
|
||||
import { AGREEMENT_TEMPLATE } from '../../../common/utils/constants/agreementTemplate';
|
||||
import { CreateActivityInput } from '../dto/createActivity.schema';
|
||||
import {
|
||||
AddPaymentDetailsDTO,
|
||||
@@ -178,93 +176,7 @@ function computeBasePriceAndTaxes(
|
||||
const normalize = (v?: string | null) =>
|
||||
v ? v.trim().toLowerCase() : null;
|
||||
|
||||
const s3 = new AWS.S3({ region: config.aws.region });
|
||||
|
||||
async function getTemplateFromS3() {
|
||||
const obj = await s3
|
||||
.getObject({
|
||||
Bucket: config.aws.bucketName,
|
||||
Key: 'Documents/MinglarAdmin/AgreementDoc/CopyofMinglarHostAgreement.docx',
|
||||
})
|
||||
.promise();
|
||||
|
||||
return obj.Body as Buffer;
|
||||
}
|
||||
|
||||
async function generateDocxFromTemplate(buffer: Buffer, data: any) {
|
||||
const zip = new PizZip(buffer);
|
||||
const doc = new Docxtemplater(zip);
|
||||
|
||||
doc.setData({
|
||||
companyName: data.companyName,
|
||||
companyType: data.companyType,
|
||||
fullAddress: data.fullAddress,
|
||||
effectiveDate: data.effectiveDate,
|
||||
expiryDate: data.expiryDate,
|
||||
durationText: data.durationText,
|
||||
commissionText: data.commissionText,
|
||||
acceptDate: data.acceptDate,
|
||||
});
|
||||
|
||||
doc.render();
|
||||
|
||||
return doc.getZip().generate({ type: 'nodebuffer' });
|
||||
}
|
||||
|
||||
function buildFullAddress(host: any) {
|
||||
return [
|
||||
host.address1,
|
||||
host.address2,
|
||||
host.cities?.cityName || host.cities?.name,
|
||||
host.states?.stateName || host.states?.name,
|
||||
host.countries?.countryName || host.countries?.name,
|
||||
host.pinCode,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(', ');
|
||||
}
|
||||
|
||||
function buildDurationText(host: any) {
|
||||
if (!host.durationNumber || !host.durationFrequency) {
|
||||
throw new ApiError(400, 'Duration not configured');
|
||||
}
|
||||
const numberWord = toWords(host.durationNumber);
|
||||
const freq =
|
||||
host.durationFrequency === 'month' && host.durationNumber > 1
|
||||
? 'months'
|
||||
: host.durationFrequency === 'year' && host.durationNumber > 1
|
||||
? 'years'
|
||||
: host.durationFrequency;
|
||||
|
||||
return `${numberWord} (${host.durationNumber}) ${freq}`;
|
||||
}
|
||||
|
||||
function buildExpiryDate(host: any) {
|
||||
if (!host.agreementStartDate) {
|
||||
throw new ApiError(400, 'Agreement start date missing');
|
||||
}
|
||||
|
||||
return dayjs(host.agreementStartDate)
|
||||
.add(host.durationNumber, host.durationFrequency)
|
||||
.format('DD-MMM-YY');
|
||||
}
|
||||
|
||||
function buildCommissionText(host: any) {
|
||||
if (host.isCommisionBase) {
|
||||
if (!host.commisionPer) {
|
||||
throw new ApiError(400, 'Commission % missing');
|
||||
}
|
||||
return `${host.commisionPer}% commission`;
|
||||
}
|
||||
|
||||
if (!host.amountPerBooking) {
|
||||
throw new ApiError(400, 'Per booking amount missing');
|
||||
}
|
||||
|
||||
return `₹${host.amountPerBooking} per booking`;
|
||||
}
|
||||
|
||||
async function generateAgreementPdfBuffer(vars: {
|
||||
async function renderAgreementPdf(vars: {
|
||||
effectiveDate: string;
|
||||
companyName: string;
|
||||
companyType?: string | null;
|
||||
@@ -275,163 +187,116 @@ async function generateAgreementPdfBuffer(vars: {
|
||||
acceptDate: string;
|
||||
}) {
|
||||
const pdfDoc = await PDFDocument.create();
|
||||
const page = pdfDoc.addPage([595, 842]); // A4
|
||||
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
|
||||
const fontBold = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
|
||||
|
||||
const { width, height } = page.getSize();
|
||||
const fontSize = 10;
|
||||
const titleSize = 14;
|
||||
const margin = 50;
|
||||
let cursorY = height - margin;
|
||||
const lineHeight = 18;
|
||||
const { width, height } = { width: 595, height: 842 }; // A4
|
||||
const contentWidth = width - 2 * margin;
|
||||
|
||||
const drawLine = (text: string, bold = false) => {
|
||||
page.drawText(text, {
|
||||
x: margin,
|
||||
y: cursorY,
|
||||
size: 12,
|
||||
font: bold ? fontBold : font,
|
||||
color: rgb(0, 0, 0),
|
||||
});
|
||||
cursorY -= lineHeight;
|
||||
let page = pdfDoc.addPage([width, height]);
|
||||
let cursorY = height - margin;
|
||||
|
||||
const addNewPage = () => {
|
||||
page = pdfDoc.addPage([width, height]);
|
||||
cursorY = height - margin;
|
||||
};
|
||||
|
||||
// Title
|
||||
page.drawText('HOST AGREEMENT', {
|
||||
x: margin,
|
||||
y: cursorY,
|
||||
size: 16,
|
||||
font: fontBold,
|
||||
color: rgb(0, 0, 0),
|
||||
});
|
||||
cursorY -= lineHeight * 2;
|
||||
const drawLine = (text: string, isBold = false, size = fontSize) => {
|
||||
const currentFont = isBold ? fontBold : font;
|
||||
const words = text.split(' ');
|
||||
let line = '';
|
||||
|
||||
drawLine(`Effective Date: ${vars.effectiveDate}`, true);
|
||||
drawLine(`Host Legal Name: ${vars.companyName}`);
|
||||
if (vars.companyType) {
|
||||
drawLine(`Company Type: ${vars.companyType}`);
|
||||
for (const word of words) {
|
||||
const testLine = line + word + ' ';
|
||||
const testLineWidth = currentFont.widthOfTextAtSize(testLine.trim(), size);
|
||||
|
||||
if (testLineWidth > contentWidth && line !== '') {
|
||||
if (cursorY < margin + 20) addNewPage();
|
||||
page.drawText(line.trim(), { x: margin, y: cursorY, size, font: currentFont });
|
||||
cursorY -= size * 1.5;
|
||||
line = word + ' ';
|
||||
} else {
|
||||
line = testLine;
|
||||
}
|
||||
}
|
||||
drawLine(`Address: ${vars.fullAddress}`);
|
||||
cursorY -= lineHeight;
|
||||
|
||||
drawLine(`Agreement Duration: ${vars.durationText}`);
|
||||
drawLine(`Expiry Date: ${vars.expiryDate}`);
|
||||
drawLine(`Commercials: ${vars.commissionText}`);
|
||||
cursorY -= lineHeight * 2;
|
||||
if (line !== '') {
|
||||
if (cursorY < margin + 20) addNewPage();
|
||||
page.drawText(line.trim(), { x: margin, y: cursorY, size, font: currentFont });
|
||||
cursorY -= size * 1.5;
|
||||
}
|
||||
};
|
||||
|
||||
drawLine('Host:', true);
|
||||
drawLine(vars.companyName);
|
||||
drawLine(`Date of Acceptance: ${vars.acceptDate}`);
|
||||
let template = AGREEMENT_TEMPLATE;
|
||||
template = template.replace(/\[EFFECTIVE_DATE\]/g, vars.effectiveDate);
|
||||
template = template.replace(/\[HOST_LEGAL_NAME\]/g, vars.companyName);
|
||||
template = template.replace(/\[COMPANY_TYPE\]/g, vars.companyType || 'Entity');
|
||||
template = template.replace(/\[FULL_ADDRESS\]/g, vars.fullAddress);
|
||||
template = template.replace(/\[DURATION_TEXT\]/g, vars.durationText);
|
||||
template = template.replace(/\[EXPIRY_DATE\]/g, vars.expiryDate);
|
||||
template = template.replace(/\[COMMISSION_TEXT\]/g, vars.commissionText);
|
||||
template = template.replace(/\[ACCEPT_DATE\]/g, vars.acceptDate);
|
||||
|
||||
const lines = template.split('\n');
|
||||
for (const line of lines) {
|
||||
const trimmed = line.trim();
|
||||
if (!trimmed) {
|
||||
cursorY -= fontSize; // Paragraph spacing
|
||||
continue;
|
||||
}
|
||||
|
||||
// Heuristic for titles/headers
|
||||
const isTitle = trimmed === trimmed.toUpperCase() && trimmed.length > 5;
|
||||
const isSubHeader = /^\d+\.?\s/.test(trimmed) || /^[A-Z]\)\s/.test(trimmed);
|
||||
|
||||
drawLine(trimmed, isTitle || isSubHeader, isTitle ? titleSize : fontSize);
|
||||
}
|
||||
|
||||
const pdfBytes = await pdfDoc.save();
|
||||
return Buffer.from(pdfBytes);
|
||||
}
|
||||
|
||||
async function generateAgreementDocxBuffer(vars: {
|
||||
effectiveDate: string;
|
||||
companyName: string;
|
||||
companyType?: string | null;
|
||||
fullAddress: string;
|
||||
durationText: string;
|
||||
expiryDate: string;
|
||||
commissionText: string;
|
||||
acceptDate: string;
|
||||
}) {
|
||||
const paragraphs: Paragraph[] = [];
|
||||
|
||||
paragraphs.push(
|
||||
new Paragraph({
|
||||
children: [
|
||||
new TextRun({
|
||||
text: 'HOST AGREEMENT',
|
||||
bold: true,
|
||||
size: 32,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
paragraphs.push(
|
||||
new Paragraph({
|
||||
children: [
|
||||
new TextRun({
|
||||
text: `Effective Date: ${vars.effectiveDate}`,
|
||||
bold: true,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
paragraphs.push(
|
||||
new Paragraph({
|
||||
children: [
|
||||
new TextRun(`Host Legal Name: ${vars.companyName}`),
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
if (vars.companyType) {
|
||||
paragraphs.push(
|
||||
new Paragraph({
|
||||
children: [new TextRun(`Company Type: ${vars.companyType}`)],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
paragraphs.push(
|
||||
new Paragraph({
|
||||
children: [new TextRun(`Address: ${vars.fullAddress}`)],
|
||||
}),
|
||||
);
|
||||
|
||||
paragraphs.push(
|
||||
new Paragraph({
|
||||
children: [new TextRun(`Agreement Duration: ${vars.durationText}`)],
|
||||
}),
|
||||
);
|
||||
|
||||
paragraphs.push(
|
||||
new Paragraph({
|
||||
children: [new TextRun(`Expiry Date: ${vars.expiryDate}`)],
|
||||
}),
|
||||
);
|
||||
|
||||
paragraphs.push(
|
||||
new Paragraph({
|
||||
children: [new TextRun(`Commercials: ${vars.commissionText}`)],
|
||||
}),
|
||||
);
|
||||
|
||||
paragraphs.push(
|
||||
new Paragraph({
|
||||
children: [new TextRun({ text: 'Host:', bold: true })],
|
||||
}),
|
||||
);
|
||||
|
||||
paragraphs.push(
|
||||
new Paragraph({
|
||||
children: [new TextRun(vars.companyName)],
|
||||
}),
|
||||
);
|
||||
|
||||
paragraphs.push(
|
||||
new Paragraph({
|
||||
children: [new TextRun(`Date of Acceptance: ${vars.acceptDate}`)],
|
||||
}),
|
||||
);
|
||||
|
||||
const doc = new Document({
|
||||
sections: [
|
||||
{
|
||||
properties: {},
|
||||
children: paragraphs,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const buffer = await Packer.toBuffer(doc);
|
||||
return buffer;
|
||||
function buildDurationText(host: any) {
|
||||
if (!host.durationNumber || !host.durationFrequency) return 'N/A';
|
||||
return `${host.durationNumber} ${host.durationFrequency}`;
|
||||
}
|
||||
|
||||
function buildExpiryDate(host: any) {
|
||||
if (!host.agreementStartDate || !host.durationNumber || !host.durationFrequency) return 'N/A';
|
||||
const start = dayjs(host.agreementStartDate);
|
||||
const duration = host.durationNumber;
|
||||
// Handle frequency units for dayjs (months/years)
|
||||
const unit = host.durationFrequency.toLowerCase().includes('month') ? 'month' : 'year';
|
||||
return start.add(duration, unit as any).format('DD-MMM-YY');
|
||||
}
|
||||
|
||||
function buildCommissionText(host: any) {
|
||||
if (host.isCommisionBase) {
|
||||
return `${host.commisionPer || 0}%`;
|
||||
} else {
|
||||
return `INR ${host.amountPerBooking || 0} per booking`;
|
||||
}
|
||||
}
|
||||
|
||||
function buildFullAddress(host: any) {
|
||||
const parts = [
|
||||
host.address1,
|
||||
host.address2,
|
||||
host.cities?.cityName,
|
||||
host.states?.stateName,
|
||||
host.countries?.countryName,
|
||||
host.pinCode,
|
||||
].filter(Boolean);
|
||||
return parts.join(', ');
|
||||
}
|
||||
|
||||
// generateAgreementPdfBuffer and generateAgreementDocxBuffer removed
|
||||
|
||||
// End of agreement rendering logic
|
||||
|
||||
const findOrCreateCountry = async (
|
||||
tx: any,
|
||||
countryName?: string | null,
|
||||
@@ -518,6 +383,9 @@ const findOrCreateCity = async (
|
||||
|
||||
|
||||
const bucket = config.aws.bucketName;
|
||||
const s3 = new AWS.S3({
|
||||
region: config.aws.region,
|
||||
});
|
||||
|
||||
@Injectable()
|
||||
export class HostService {
|
||||
@@ -1047,9 +915,7 @@ export class HostService {
|
||||
acceptDate,
|
||||
};
|
||||
|
||||
const templateBuffer = await getTemplateFromS3();
|
||||
const docxBuffer = await generateDocxFromTemplate(templateBuffer, agreementVars);
|
||||
const pdfBuffer = await generateAgreementPdfBuffer(agreementVars);
|
||||
const pdfBuffer = await renderAgreementPdf(agreementVars);
|
||||
|
||||
const existingCount = await this.prisma.hostAgreement.count({
|
||||
where: { hostXid: host.id, isActive: true },
|
||||
@@ -1058,20 +924,8 @@ export class HostService {
|
||||
const nextVersionNumber = `AG${existingCount + 1}`;
|
||||
const baseKey = `Documents/Host/${host.id}/agreements/${nextVersionNumber}`;
|
||||
|
||||
const docxKey = `${baseKey}.docx`;
|
||||
const pdfKey = `${baseKey}.pdf`;
|
||||
|
||||
await s3
|
||||
.upload({
|
||||
Bucket: config.aws.bucketName,
|
||||
Key: docxKey,
|
||||
Body: docxBuffer,
|
||||
ContentType:
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
ACL: 'private',
|
||||
})
|
||||
.promise();
|
||||
|
||||
await s3
|
||||
.upload({
|
||||
Bucket: config.aws.bucketName,
|
||||
|
||||
Reference in New Issue
Block a user