Initial commit
This commit is contained in:
commit
41d230d524
163 files changed
+11500
No files matched your search
@@ -0,0 +1,203 @@
|
||||
// ==========================================
|
||||
// PROFILE: ТЕХНИКО-КОММЕРЧЕСКОЕ ПРЕДЛОЖЕНИЕ
|
||||
// ==========================================
|
||||
#import "../../domain/document.typ": document-profile, fail
|
||||
#import "../../domain/attachments.typ": attachment-set
|
||||
#import "../../domain/parties.typ": signer
|
||||
#import "../foundation.typ": apply-foundation
|
||||
#import "../components.typ": attachment-list, appendix-heading, company-footer, letter-header, signature-block
|
||||
|
||||
#let commercial-terms(
|
||||
amount: none,
|
||||
currency: "RUB",
|
||||
tax_note: none,
|
||||
delivery_term: none,
|
||||
validity: none,
|
||||
payment_terms: none,
|
||||
) = {
|
||||
(
|
||||
amount: amount,
|
||||
currency: currency,
|
||||
tax-note: tax_note,
|
||||
delivery-term: delivery_term,
|
||||
validity: validity,
|
||||
payment-terms: payment_terms,
|
||||
)
|
||||
}
|
||||
|
||||
#let normalize-offer(metadata) = {
|
||||
if type(metadata.attachments) == array {
|
||||
metadata.insert("attachments", attachment-set(items: metadata.attachments))
|
||||
}
|
||||
metadata
|
||||
}
|
||||
|
||||
#let validate-offer(metadata) = {
|
||||
if metadata.recipient == none or type(metadata.recipient) != dictionary or metadata.recipient.at("kind", default: none) != "recipient" {
|
||||
fail("commercial-offer.recipient", "ожидался recipient")
|
||||
}
|
||||
if type(metadata.subject) != str or metadata.subject.trim() == "" {
|
||||
fail("commercial-offer.subject", "предмет предложения обязателен")
|
||||
}
|
||||
if type(metadata.terms) != dictionary {
|
||||
fail("commercial-offer.terms", "ожидался commercial-terms")
|
||||
}
|
||||
if metadata.terms.amount == none {
|
||||
fail("commercial-offer.terms.amount", "стоимость обязательна")
|
||||
}
|
||||
if type(metadata.attachments) != dictionary or metadata.attachments.at("kind", default: none) != "attachment-set" {
|
||||
fail("commercial-offer.attachments", "ожидался attachment-set")
|
||||
}
|
||||
metadata
|
||||
}
|
||||
|
||||
#let effective-offer-signer(data, company, include-media: true) = {
|
||||
let source = if data.signer == none {
|
||||
signer(
|
||||
company.director.name,
|
||||
company.director.title,
|
||||
signature: company.resources.signature,
|
||||
stamp: company.resources.stamp,
|
||||
)
|
||||
} else {
|
||||
data.signer
|
||||
}
|
||||
signer(
|
||||
source.name,
|
||||
source.title,
|
||||
basis: source.basis,
|
||||
signature: if include-media { source.signature } else { none },
|
||||
stamp: if include-media { source.stamp } else { none },
|
||||
)
|
||||
}
|
||||
|
||||
#let offer-summary(data) = {
|
||||
let terms = data.terms
|
||||
set par(first-line-indent: 0pt, justify: false, leading: 0.7em)
|
||||
table(
|
||||
columns: (4cm, 1fr),
|
||||
stroke: 0.5pt + luma(170),
|
||||
inset: 6pt,
|
||||
fill: (x, _) => if x == 0 { luma(245) } else { none },
|
||||
[*Предмет*], [#data.subject],
|
||||
[*Стоимость*], [#terms.amount #terms.currency],
|
||||
..if terms.at("tax-note") != none { ([*Налоги*], [#terms.at("tax-note")]) } else { () },
|
||||
..if terms.at("delivery-term") != none { ([*Срок выполнения*], [#terms.at("delivery-term")]) } else { () },
|
||||
..if terms.validity != none { ([*Срок действия*], [#terms.validity]) } else { () },
|
||||
..if terms.at("payment-terms") != none { ([*Порядок оплаты*], [#terms.at("payment-terms")]) } else { () },
|
||||
)
|
||||
}
|
||||
|
||||
#let render-offer-attachments(attachments, appendix-state) = {
|
||||
for (index, item) in attachments.items.enumerate() {
|
||||
pagebreak()
|
||||
appendix-state.update(true)
|
||||
let number = if item.number == auto { index + attachments.start } else { item.number }
|
||||
appendix-heading(item, str(number))
|
||||
v(0.5cm)
|
||||
if type(item.body) == function { (item.body)() } else { item.body }
|
||||
}
|
||||
}
|
||||
|
||||
#let render-commercial-offer(body, ctx) = {
|
||||
let company = ctx.company
|
||||
let data = ctx.metadata
|
||||
let include-media = ctx.options.mode == "final"
|
||||
let person = effective-offer-signer(data, company, include-media: include-media)
|
||||
let media-policy = if include-media { ctx.options.at("media-policy") } else { "reserve-space" }
|
||||
let appendix-state = state("scientia-offer-in-appendix", false)
|
||||
let footer = context {
|
||||
if not appendix-state.get() { company-footer(company) }
|
||||
}
|
||||
let composed = [
|
||||
#letter-header(
|
||||
company,
|
||||
data.recipient,
|
||||
date: data.date,
|
||||
reference: data.reference,
|
||||
title: data.title,
|
||||
media_policy: ctx.options.at("media-policy"),
|
||||
)
|
||||
#v(0.6cm)
|
||||
#offer-summary(data)
|
||||
#v(0.7cm)
|
||||
#body
|
||||
#if data.attachments.items.len() > 0 {
|
||||
v(0.8cm)
|
||||
attachment-list(data.attachments)
|
||||
}
|
||||
#signature-block(
|
||||
person,
|
||||
company: company,
|
||||
media_policy: media-policy,
|
||||
show_stamp: data.at("show-stamp"),
|
||||
note: data.note,
|
||||
)
|
||||
#if data.at("render-attachments") and data.attachments.items.len() > 0 {
|
||||
render-offer-attachments(data.attachments, appendix-state)
|
||||
}
|
||||
]
|
||||
|
||||
apply-foundation(
|
||||
composed,
|
||||
ctx: ctx,
|
||||
tokens: (
|
||||
text-font: "Arial",
|
||||
text-size: 10pt,
|
||||
line-height: 0.65em,
|
||||
page-margin: (top: 1.5cm, bottom: 4cm, left: 1.5cm, right: 1.5cm),
|
||||
),
|
||||
page-options: (
|
||||
footer: footer,
|
||||
footer-descent: 20%,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#let commercial-offer-profile(
|
||||
recipient: none,
|
||||
subject: "",
|
||||
amount: none,
|
||||
currency: "RUB",
|
||||
tax_note: none,
|
||||
delivery_term: none,
|
||||
validity: none,
|
||||
payment_terms: none,
|
||||
date: none,
|
||||
reference: none,
|
||||
title: "Технико-коммерческое предложение",
|
||||
signer: none,
|
||||
note: none,
|
||||
show_stamp: true,
|
||||
attachments: attachment-set(),
|
||||
render_attachments: true,
|
||||
) = {
|
||||
document-profile(
|
||||
"commercial-offer",
|
||||
render-commercial-offer,
|
||||
metadata: (
|
||||
recipient: recipient,
|
||||
subject: subject,
|
||||
terms: commercial-terms(
|
||||
amount: amount,
|
||||
currency: currency,
|
||||
tax_note: tax_note,
|
||||
delivery_term: delivery_term,
|
||||
validity: validity,
|
||||
payment_terms: payment_terms,
|
||||
),
|
||||
date: date,
|
||||
reference: reference,
|
||||
title: title,
|
||||
signer: signer,
|
||||
note: note,
|
||||
show-stamp: show_stamp,
|
||||
parties: (),
|
||||
attachments: attachments,
|
||||
bibliographies: (),
|
||||
render-attachments: render_attachments,
|
||||
),
|
||||
normalize: normalize-offer,
|
||||
validate: validate-offer,
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user