changeset db7d7f741246 in modules/sale_gift_card:default
details:
https://hg.tryton.org/modules/sale_gift_card?cmd=changeset&node=db7d7f741246
description:
Manage gift card on POS
issue8737
review21391002
diffstat:
CHANGELOG | 2 +
__init__.py | 10 +
gift_card.fodt | 287 ++++++++++++++++++++++++++++
sale.py | 221 +++++++++++++++++++++-
sale.xml | 41 ++++
tests/scenario_sale_gift_card.rst | 8 +-
tests/scenario_sale_point_gift_card.rst | 223 +++++++++++++++++++++
tests/test_sale_gift_card.py | 6 +
tryton.cfg | 2 +
view/sale_point_sale_form.xml | 10 +
view/sale_point_sale_line_form.xml | 13 +
view/sale_point_sale_pay_gift_card_form.xml | 14 +
12 files changed, 834 insertions(+), 3 deletions(-)
diffs (963 lines):
diff -r 58aa1f26ab0f -r db7d7f741246 CHANGELOG
--- a/CHANGELOG Sun Sep 26 23:11:21 2021 +0200
+++ b/CHANGELOG Mon Oct 11 23:55:17 2021 +0200
@@ -1,2 +1,4 @@
+* Manage gift card on POS
+
Version 6.0.0 - 2021-05-03
* Initial release
diff -r 58aa1f26ab0f -r db7d7f741246 __init__.py
--- a/__init__.py Sun Sep 26 23:11:21 2021 +0200
+++ b/__init__.py Mon Oct 11 23:55:17 2021 +0200
@@ -29,5 +29,15 @@
Pool.register(
module='sale_gift_card', type_='wizard')
Pool.register(
+ sale.GiftCardReport,
sale.GiftCardEmail,
module='sale_gift_card', type_='report')
+ Pool.register(
+ sale.GiftCard_POS,
+ sale.POSSale,
+ sale.POSSaleLine,
+ sale.POSPayGiftCard,
+ module='sale_gift_card', type_='model', depends=['sale_point'])
+ Pool.register(
+ sale.POSPay,
+ module='sale_gift_card', type_='wizard', depends=['sale_point'])
diff -r 58aa1f26ab0f -r db7d7f741246 gift_card.fodt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gift_card.fodt Mon Oct 11 23:55:17 2021 +0200
@@ -0,0 +1,287 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:officeooo="http://openoffice.org/2009/office"
xmlns:css3t="http://www.w3.org/TR/css3-text/"
xmlns:grddl="http://www.w3.org/2003/g/data-view#"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
xmlns:oooc="http://openoffice.org/2004/calc"
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
xmlns:ooow="http://openoffice.org/2004/writer"
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:rpt="http://openoffice.org/2005/report"
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
xmlns:ooo="http://openoffice.org/2004/office"
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2"
xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"
xmlns:tableooo="http://openoffice.org/2009/table"
xmlns:drawooo="http://openoffice.org/2010/draw"
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
xmlns:dom="http://www.w3.org/2001/xml-events"
xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0"
xmlns:math="http://www.w3.org/1998/Math/MathML"
xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
xmlns:xforms="http://www.w3.org/2002/xforms" office:version="1.3"
office:mimetype="application/vnd.oasis.opendocument.text">
+
<office:meta><meta:creation-date>2021-08-24T17:09:33.815571391</meta:creation-date><meta:generator>LibreOffice/7.1.3.2$Linux_X86_64
LibreOffice_project/10$Build-2</meta:generator><dc:date>2021-08-24T17:22:12.187453618</dc:date><meta:editing-duration>PT12M35S</meta:editing-duration><meta:editing-cycles>7</meta:editing-cycles><meta:document-statistic
meta:table-count="0" meta:image-count="0" meta:object-count="0"
meta:page-count="2" meta:paragraph-count="5" meta:word-count="11"
meta:character-count="127"
meta:non-whitespace-character-count="121"/></office:meta>
+ <office:settings>
+ <config:config-item-set config:name="ooo:view-settings">
+ <config:config-item config:name="ViewAreaTop"
config:type="long">0</config:config-item>
+ <config:config-item config:name="ViewAreaLeft"
config:type="long">0</config:config-item>
+ <config:config-item config:name="ViewAreaWidth"
config:type="long">17323</config:config-item>
+ <config:config-item config:name="ViewAreaHeight"
config:type="long">8592</config:config-item>
+ <config:config-item config:name="ShowRedlineChanges"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="InBrowseMode"
config:type="boolean">false</config:config-item>
+ <config:config-item-map-indexed config:name="Views">
+ <config:config-item-map-entry>
+ <config:config-item config:name="ViewId"
config:type="string">view2</config:config-item>
+ <config:config-item config:name="ViewLeft"
config:type="long">1136</config:config-item>
+ <config:config-item config:name="ViewTop"
config:type="long">1512</config:config-item>
+ <config:config-item config:name="VisibleLeft"
config:type="long">0</config:config-item>
+ <config:config-item config:name="VisibleTop"
config:type="long">0</config:config-item>
+ <config:config-item config:name="VisibleRight"
config:type="long">17321</config:config-item>
+ <config:config-item config:name="VisibleBottom"
config:type="long">8590</config:config-item>
+ <config:config-item config:name="ZoomType"
config:type="short">0</config:config-item>
+ <config:config-item config:name="ViewLayoutColumns"
config:type="short">0</config:config-item>
+ <config:config-item config:name="ViewLayoutBookMode"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="ZoomFactor"
config:type="short">280</config:config-item>
+ <config:config-item config:name="IsSelectedFrame"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="AnchoredTextOverflowLegacy"
config:type="boolean">false</config:config-item>
+ </config:config-item-map-entry>
+ </config:config-item-map-indexed>
+ </config:config-item-set>
+ <config:config-item-set config:name="ooo:configuration-settings">
+ <config:config-item config:name="PrintProspect"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="PrintReversed"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="PrintSingleJobs"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="PrintLeftPages"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="PrintTables"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="PrintControls"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="PrintPageBackground"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="PrintDrawings"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="PrintBlackFonts"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="PrintAnnotationMode"
config:type="short">0</config:config-item>
+ <config:config-item config:name="PrintTextPlaceholder"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="ProtectFields"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="ProtectBookmarks"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="EmptyDbFieldHidesPara"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="DisableOffPagePositioning"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="SubtractFlysAnchoredAtFlys"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="PropLineSpacingShrinksFirstLine"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="ApplyParagraphMarkFormatToNumbering"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="TreatSingleColumnBreakAsPageBreak"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="EmbedSystemFonts"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="EmbedComplexScriptFonts"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="EmbedAsianScriptFonts"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="EmbedLatinScriptFonts"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="EmbedOnlyUsedFonts"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="ContinuousEndnotes"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="EmbedFonts"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="ClippedPictures"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="FloattableNomargins"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="UnbreakableNumberings"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="HeaderSpacingBelowLastPara"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="AllowPrintJobCancel"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="UseOldPrinterMetrics"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="TabOverMargin"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="TabsRelativeToIndent"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="UseOldNumbering"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="InvertBorderSpacing"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="PrintPaperFromSetup"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="UpdateFromTemplate"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="CurrentDatabaseCommandType"
config:type="int">0</config:config-item>
+ <config:config-item config:name="LinkUpdateMode"
config:type="short">1</config:config-item>
+ <config:config-item config:name="AddParaSpacingToTableCells"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="FrameAutowidthWithMorePara"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="CurrentDatabaseCommand"
config:type="string"/>
+ <config:config-item config:name="PrinterIndependentLayout"
config:type="string">high-resolution</config:config-item>
+ <config:config-item config:name="ApplyUserData"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="PrintFaxName" config:type="string"/>
+ <config:config-item config:name="CurrentDatabaseDataSource"
config:type="string"/>
+ <config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsKernAsianPunctuation"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="SaveThumbnail"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="UseFormerTextWrapping"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="AddExternalLeading"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="AddParaTableSpacing"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="StylesNoDefault"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="ChartAutoUpdate"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="PrinterSetup"
config:type="base64Binary">mwH+/1JJQ09IX0FmaWNpb18yMDIwRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ1VQUzpSSUNPSF9BZmljaW9fMjAyMEQAAAAAAAAAAAAWAAMAtwAAAAAAAAAEAAhSAAAEdAAASm9iRGF0YSAxCnByaW50ZXI9UklDT0hfQWZpY2lvXzIwMjBECm9yaWVudGF0aW9uPVBvcnRyYWl0CmNvcGllcz0xCmNvbGxhdGU9ZmFsc2UKbWFyZ2luZGFqdXN0bWVudD0wLDAsMCwwCmNvbG9yZGVwdGg9MjQKcHNsZXZlbD0wCnBkZmRldmljZT0xCmNvbG9yZGV2aWNlPTAKUFBEQ29udGV4RGF0YQpQYWdlU2l6ZTpBNAAAEgBDT01QQVRfRFVQTEVYX01PREUUAER1cGxleE1vZGU6OkxvbmdFZGdl</config:config-item>
+ <config:config-item config:name="AddParaTableSpacingAtStart"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="Rsid"
config:type="int">1111966</config:config-item>
+ <config:config-item config:name="EmbeddedDatabaseName"
config:type="string"/>
+ <config:config-item config:name="FieldAutoUpdate"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="OutlineLevelYieldsNumbering"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="AlignTabStopPosition"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="CharacterCompressionType"
config:type="short">0</config:config-item>
+ <config:config-item config:name="PrinterName"
config:type="string">RICOH_Aficio_2020D</config:config-item>
+ <config:config-item config:name="SaveGlobalDocumentLinks"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="PrinterPaperFromSetup"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="UseFormerLineSpacing"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="AddParaLineSpacingToTableCells"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="UseFormerObjectPositioning"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="PrintGraphics"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="SurroundTextWrapSmall"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="ConsiderTextWrapOnObjPos"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="MsWordCompTrailingBlanks"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="TabAtLeftIndentForParagraphsInList"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="PrintRightPages"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IgnoreFirstLineIndentInNumbering"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="RedlineProtectionKey"
config:type="base64Binary"/>
+ <config:config-item config:name="DoNotJustifyLinesWithManualBreak"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="PrintProspectRTL"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="PrintEmptyPages"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="DoNotResetParaAttrsForNumFont"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="AddFrameOffsets"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="LoadReadonly"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="DoNotCaptureDrawObjsOnPage"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="AddVerticalFrameOffsets"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="UnxForceZeroExtLeading"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsLabelDocument"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="TableRowKeep"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="RsidRoot"
config:type="int">1111966</config:config-item>
+ <config:config-item config:name="PrintHiddenText"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="ProtectForm"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="MsWordCompMinLineHeightByFly"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="BackgroundParaOverDrawings"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="SaveVersionOnClose"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="MathBaselineAlignment"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="SmallCapsPercentage66"
config:type="boolean">false</config:config-item>
+ <config:config-item config:name="CollapseEmptyCellPara"
config:type="boolean">true</config:config-item>
+ <config:config-item config:name="TabOverflow"
config:type="boolean">true</config:config-item>
+ </config:config-item-set>
+ </office:settings>
+ <office:scripts>
+ <office:script script:language="ooo:Basic">
+ <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office"
xmlns:xlink="http://www.w3.org/1999/xlink"/>
+ </office:script>
+ </office:scripts>
+ <office:font-face-decls>
+ <style:font-face style:name="Noto Sans Devanagari1"
svg:font-family="'Noto Sans Devanagari'"
style:font-family-generic="swiss"/>
+ <style:font-face style:name="Liberation Serif"
svg:font-family="'Liberation Serif'"
style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Liberation Sans"
svg:font-family="'Liberation Sans'" style:font-family-generic="swiss"
style:font-pitch="variable"/>
+ <style:font-face style:name="Liberation Sans1"
svg:font-family="'Liberation Sans'"
style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="Noto Sans Devanagari"
svg:font-family="'Noto Sans Devanagari'"
style:font-family-generic="system" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+ <style:default-style style:family="graphic">
+ <style:graphic-properties svg:stroke-color="#3465a4"
draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm"
draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm"
draw:start-line-spacing-vertical="0.283cm"
draw:end-line-spacing-horizontal="0.283cm"
draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/>
+ <style:paragraph-properties style:text-autospace="ideograph-alpha"
style:line-break="strict" style:writing-mode="lr-tb"
style:font-independent-line-spacing="false">
+ <style:tab-stops/>
+ </style:paragraph-properties>
+ <style:text-properties style:use-window-font-color="true"
loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt"
fo:language="fr" fo:country="BE" style:letter-kerning="true"
style:font-name-asian="Liberation Sans1" style:font-size-asian="10.5pt"
style:language-asian="zh" style:country-asian="CN"
style:font-name-complex="Noto Sans Devanagari" style:font-size-complex="12pt"
style:language-complex="hi" style:country-complex="IN"/>
+ </style:default-style>
+ <style:default-style style:family="paragraph">
+ <style:paragraph-properties fo:orphans="2" fo:widows="2"
fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha"
style:punctuation-wrap="hanging" style:line-break="strict"
style:tab-stop-distance="1.251cm" style:writing-mode="page"/>
+ <style:text-properties style:use-window-font-color="true"
loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt"
fo:language="fr" fo:country="BE" style:letter-kerning="true"
style:font-name-asian="Liberation Sans1" style:font-size-asian="10.5pt"
style:language-asian="zh" style:country-asian="CN"
style:font-name-complex="Noto Sans Devanagari" style:font-size-complex="12pt"
style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false"
fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"
loext:hyphenation-no-caps="false"/>
+ </style:default-style>
+ <style:default-style style:family="table">
+ <style:table-properties table:border-model="collapsing"/>
+ </style:default-style>
+ <style:default-style style:family="table-row">
+ <style:table-row-properties fo:keep-together="auto"/>
+ </style:default-style>
+ <style:style style:name="Standard" style:family="paragraph"
style:class="text"/>
+ <style:style style:name="Heading" style:family="paragraph"
style:parent-style-name="Standard" style:next-style-name="Text_20_body"
style:class="text">
+ <style:paragraph-properties fo:margin-top="0.423cm"
fo:margin-bottom="0.212cm" style:contextual-spacing="false"
fo:keep-with-next="always"/>
+ <style:text-properties style:font-name="Liberation Sans"
fo:font-family="'Liberation Sans'" style:font-family-generic="swiss"
style:font-pitch="variable" fo:font-size="14pt"
style:font-name-asian="Liberation Sans1"
style:font-family-asian="'Liberation Sans'"
style:font-family-generic-asian="system" style:font-pitch-asian="variable"
style:font-size-asian="14pt" style:font-name-complex="Noto Sans Devanagari"
style:font-family-complex="'Noto Sans Devanagari'"
style:font-family-generic-complex="system" style:font-pitch-complex="variable"
style:font-size-complex="14pt"/>
+ </style:style>
+ <style:style style:name="Text_20_body" style:display-name="Text body"
style:family="paragraph" style:parent-style-name="Standard" style:class="text">
+ <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0.247cm"
style:contextual-spacing="false" fo:line-height="115%"/>
+ </style:style>
+ <style:style style:name="List" style:family="paragraph"
style:parent-style-name="Text_20_body" style:class="list">
+ <style:text-properties style:font-size-asian="12pt"
style:font-name-complex="Noto Sans Devanagari1"
style:font-family-complex="'Noto Sans Devanagari'"
style:font-family-generic-complex="swiss"/>
+ </style:style>
+ <style:style style:name="Caption" style:family="paragraph"
style:parent-style-name="Standard" style:class="extra">
+ <style:paragraph-properties fo:margin-top="0.212cm"
fo:margin-bottom="0.212cm" style:contextual-spacing="false"
text:number-lines="false" text:line-number="0"/>
+ <style:text-properties fo:font-size="12pt" fo:font-style="italic"
style:font-size-asian="12pt" style:font-style-asian="italic"
style:font-name-complex="Noto Sans Devanagari1"
style:font-family-complex="'Noto Sans Devanagari'"
style:font-family-generic-complex="swiss" style:font-size-complex="12pt"
style:font-style-complex="italic"/>
+ </style:style>
+ <style:style style:name="Index" style:family="paragraph"
style:parent-style-name="Standard" style:class="index">
+ <style:paragraph-properties text:number-lines="false" text:line-number="0"/>
+ <style:text-properties style:font-size-asian="12pt"
style:font-name-complex="Noto Sans Devanagari1"
style:font-family-complex="'Noto Sans Devanagari'"
style:font-family-generic-complex="swiss"/>
+ </style:style>
+ <style:style style:name="Title" style:family="paragraph"
style:parent-style-name="Heading" style:next-style-name="Text_20_body"
style:class="chapter">
+ <style:paragraph-properties fo:text-align="center"
style:justify-single-word="false"/>
+ <style:text-properties fo:font-size="28pt" fo:font-weight="bold"
style:font-size-asian="28pt" style:font-weight-asian="bold"
style:font-size-complex="28pt" style:font-weight-complex="bold"/>
+ </style:style>
+ <style:style style:name="Placeholder" style:family="text">
+ <style:text-properties fo:font-variant="small-caps" fo:color="#008080"
loext:opacity="100%" style:text-underline-style="dotted"
style:text-underline-width="auto" style:text-underline-color="font-color"/>
+ </style:style>
+ <text:outline-style style:name="Outline">
+ <text:outline-level-style text:level="1" style:num-format="">
+ <style:list-level-properties
text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="2" style:num-format="">
+ <style:list-level-properties
text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="3" style:num-format="">
+ <style:list-level-properties
text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="4" style:num-format="">
+ <style:list-level-properties
text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="5" style:num-format="">
+ <style:list-level-properties
text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="6" style:num-format="">
+ <style:list-level-properties
text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="7" style:num-format="">
+ <style:list-level-properties
text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="8" style:num-format="">
+ <style:list-level-properties
text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="9" style:num-format="">
+ <style:list-level-properties
text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="10" style:num-format="">
+ <style:list-level-properties
text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ </text:outline-style>
+ <text:notes-configuration text:note-class="footnote" style:num-format="1"
text:start-value="0" text:footnotes-position="page"
text:start-numbering-at="document"/>
+ <text:notes-configuration text:note-class="endnote" style:num-format="i"
text:start-value="0"/>
+ <text:linenumbering-configuration text:number-lines="false"
text:offset="0.499cm" style:num-format="1" text:number-position="left"
text:increment="5"/>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="P1" style:family="paragraph"
style:parent-style-name="Standard">
+ <style:text-properties fo:language="en" fo:country="US"
style:language-asian="zxx" style:country-asian="none"
style:language-complex="zxx" style:country-complex="none"/>
+ </style:style>
+ <style:style style:name="P2" style:family="paragraph"
style:parent-style-name="Text_20_body">
+ <style:paragraph-properties fo:text-align="center"
style:justify-single-word="false"/>
+ <style:text-properties fo:font-size="12pt" fo:language="en" fo:country="US"
fo:font-weight="normal" officeooo:rsid="0010f79e"
officeooo:paragraph-rsid="0010f79e" style:font-size-asian="12pt"
style:language-asian="zxx" style:country-asian="none"
style:font-weight-asian="normal" style:font-size-complex="12pt"
style:language-complex="zxx" style:country-complex="none"
style:font-weight-complex="normal"/>
+ </style:style>
+ <style:style style:name="P3" style:family="paragraph"
style:parent-style-name="Text_20_body">
+ <style:paragraph-properties fo:margin-top="0.25cm"
fo:margin-bottom="0.25cm" style:contextual-spacing="false"
fo:text-align="center" style:justify-single-word="false"/>
+ <style:text-properties fo:font-size="24pt" fo:language="en" fo:country="US"
fo:font-weight="bold" officeooo:rsid="0010f79e"
officeooo:paragraph-rsid="0010f79e" style:font-size-asian="24pt"
style:language-asian="zxx" style:country-asian="none"
style:font-weight-asian="bold" style:font-size-complex="24pt"
style:language-complex="zxx" style:country-complex="none"
style:font-weight-complex="bold"/>
+ </style:style>
+ <style:style style:name="P4" style:family="paragraph"
style:parent-style-name="Title">
+ <style:text-properties fo:font-size="16pt" fo:language="en" fo:country="US"
style:font-size-asian="16pt" style:language-asian="zxx"
style:country-asian="none" style:font-size-complex="16pt"
style:language-complex="zxx" style:country-complex="none"/>
+ </style:style>
+ <style:page-layout style:name="pm1">
+ <style:page-layout-properties fo:page-width="7.4cm" fo:page-height="5.2cm"
style:num-format="1" style:print-orientation="landscape"
fo:margin-top="0.101cm" fo:margin-bottom="0.101cm" fo:margin-left="0.101cm"
fo:margin-right="0.101cm" style:writing-mode="lr-tb"
style:footnote-max-height="0cm">
+ <style:footnote-sep style:width="0.018cm"
style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm"
style:line-style="solid" style:adjustment="left" style:rel-width="25%"
style:color="#000000"/>
+ </style:page-layout-properties>
+ <style:header-style/>
+ <style:footer-style/>
+ </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+ <style:master-page style:name="Standard" style:page-layout-name="pm1"/>
+ </office:master-styles>
+ <office:body>
+ <office:text text:use-soft-page-breaks="true">
+ <text:sequence-decls>
+ <text:sequence-decl text:display-outline-level="0"
text:name="Illustration"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Table"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Text"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
+ </text:sequence-decls>
+ <text:p text:style-name="P1"><text:placeholder
text:placeholder-type="text"><for each="card in
records"></text:placeholder></text:p>
+ <text:p text:style-name="P4"><text:placeholder
text:placeholder-type="text"><card.company.rec_name></text:placeholder></text:p>
+ <text:p text:style-name="P3"><text:placeholder
text:placeholder-type="text"><card.number></text:placeholder></text:p>
+ <text:p text:style-name="P2">Value: <text:placeholder
text:placeholder-type="text"><format_currency(card.value, None,
card.currency)></text:placeholder></text:p>
+ <text:p text:style-name="P1"><text:soft-page-break/><text:placeholder
text:placeholder-type="text"></for></text:placeholder></text:p>
+ </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff -r 58aa1f26ab0f -r db7d7f741246 sale.py
--- a/sale.py Sun Sep 26 23:11:21 2021 +0200
+++ b/sale.py Mon Oct 11 23:55:17 2021 +0200
@@ -13,6 +13,7 @@
from trytond.sendmail import sendmail_transactional
from trytond.tools.email_ import set_from_header
from trytond.transaction import Transaction
+from trytond.wizard import StateView, StateTransition, Button
from trytond.modules.company.model import CompanyValueMixin
from trytond.modules.currency.fields import Monetary
@@ -185,6 +186,8 @@
from_cfg = config.get('email', 'from')
for gift_card in gift_cards:
email = gift_card._email
+ if not email:
+ continue
languages = gift_card._languages
if not languages:
languages.append(Lang.get())
@@ -196,10 +199,63 @@
sendmail_transactional(from_cfg, [email], msg, strict=True)
+class GiftCardReport(Report):
+ __name__ = 'sale.gift_card'
+
+ @classmethod
+ def _get_records(cls, ids, model, data):
+ pool = Pool()
+ if model in {'sale.sale', 'sale.point.sale'}:
+ Sale = pool.get(model)
+ sales = Sale.browse(ids)
+ ids = [
+ g.id for s in sales
+ for line in s.lines
+ for g in line.gift_cards]
+ model = 'sale.gift_card'
+ return super()._get_records(ids, model, data)
+
+
class GiftCardEmail(Report):
__name__ = 'sale.gift_card.email'
+class GiftCard_POS(metaclass=PoolMeta):
+ __name__ = 'sale.gift_card'
+
+ @classmethod
+ def _get_origin(cls):
+ return super()._get_origin() + ['sale.point.sale.line']
+
+ @fields.depends('origin')
+ def on_change_origin(self):
+ pool = Pool()
+ POSLine = pool.get('sale.point.sale.line')
+ UOM = pool.get('product.uom')
+ if isinstance(self.origin, POSLine):
+ line = self.origin
+ self.company = line.sale.company
+ self.product = line.product
+ if line.unit and line.unit_price and line.product:
+ self.value = UOM.compute_price(
+ line.unit, line.unit_price, line.product.default_uom)
+ self.currency = line.sale.currency
+ super().on_change_origin()
+
+ @classmethod
+ def _get_spent_on(cls):
+ return super()._get_spent_on() + ['sale.point.sale']
+
+ @property
+ def _email(self):
+ pool = Pool()
+ POSLine = pool.get('sale.point.sale.line')
+ email = super()._email
+ if isinstance(self.origin, POSLine):
+ email = self.origin.gift_card_email
+ return email
+
+
class Sale(metaclass=PoolMeta):
__name__ = 'sale.sale'
@@ -270,8 +326,75 @@
super().process(sales)
-class Line(metaclass=PoolMeta):
- __name__ = 'sale.line'
+class POSSale(metaclass=PoolMeta):
+ __name__ = 'sale.point.sale'
+
+ gift_cards = fields.One2Many(
+ 'sale.gift_card', 'spent_on', "Gift Cards",
+ domain=[
+ ('company', '=', Eval('company', -1)),
+ ('currency', '=', Eval('currency', -1)),
+ ],
+ add_remove=[
+ ('spent_on', '=', None),
+ ],
+ states={
+ 'readonly': Eval('state') != 'draft',
+ },
+ depends=['state', 'company', 'currency'])
+
+ @fields.depends('state', 'gift_cards')
+ def on_change_with_total(self, name=None):
+ total = super().on_change_with_total(name=name)
+ if self.state == 'open':
+ total -= sum(c.value for c in self.gift_cards)
+ return total
+
+ @classmethod
+ @Workflow.transition('done')
+ def do(cls, sales):
+ for sale in sales:
+ sale.add_return_gift_cards()
+ cls.save(sales)
+ super().do(sales)
+ pool = Pool()
+ GiftCard = pool.get('sale.gift_card')
+ cls.lock(sales)
+ gift_cards = []
+ for sale in sales:
+ for line in sale.lines:
+ cards = line.get_gift_cards()
+ if cards:
+ gift_cards.extend(cards)
+ GiftCard.save(gift_cards)
+ GiftCard.send(gift_cards)
+
+ # TODO: print gift cards
+
+ def add_return_gift_cards(self):
+ lines = list(self.lines)
+ for line in self.lines:
+ if line.is_gift_card and line.quantity < 0:
+ lines.remove(line)
+ for gift_card in self.gift_cards:
+ lines.append(self.get_return_gift_card_line(gift_card))
+ self.lines = lines
+
+ def get_return_gift_card_line(self, gift_card):
+ pool = Pool()
+ Line = pool.get('sale.point.sale.line')
+ return Line(
+ sale=self,
+ product=gift_card.product,
+ quantity=-1,
+ unit=gift_card.product.default_uom,
+ unit_list_price=gift_card.value,
+ unit_gross_price=gift_card.value,
+ )
+
+
+class _LineMixin:
+ __slots__ = ()
gift_cards = fields.One2Many(
'sale.gift_card', 'origin', "Gift Cards", readonly=True,
@@ -339,3 +462,97 @@
card.origin = self
cards.append(card)
return cards
+
+
+class Line(_LineMixin, metaclass=PoolMeta):
+ __name__ = 'sale.line'
+
+
+class POSSaleLine(_LineMixin, metaclass=PoolMeta):
+ __name__ = 'sale.point.sale.line'
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ # Prevent selling goods gift card as POS does not manage shipment
+ cls.product.domain = [
+ cls.product.domain,
+ ['OR',
+ ('gift_card', '!=', True),
+ ('type', '=', 'service'),
+ ],
+ ]
+
+
+class POSPay(metaclass=PoolMeta):
+ __name__ = 'sale.point.sale.pay'
+
+ gift_card = StateView(
+ 'sale.point.sale.pay.gift_card',
+ 'sale_gift_card.sale_point_sale_pay_gift_card_view_form', [
+ Button("Cancel", 'end', 'tryton-cancel'),
+ Button("Add", 'add_gift_card', 'tryton-ok', default=True),
+ ])
+ add_gift_card = StateTransition()
+
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ cls.payment.buttons.insert(-1, Button(
+ "Gift Card", 'gift_card',
+ states={
+ 'invisible': Eval('amount', 0) >= 0,
+ },
+ validate=False))
+
+ def default_gift_card(self, fields):
+ return {
+ 'sale': self.record.id,
+ 'amount': -self.record.amount_to_pay,
+ }
+
+ def transition_add_gift_card(self):
+ self._add_gift_card().save()
+ if self.record.amount_to_pay:
+ return 'payment'
+ else:
+ self.model.process([self.record])
+ return 'end'
+
+ def _add_gift_card(self):
+ pool = Pool()
+ Line = pool.get('sale.point.sale.line')
+ return Line(
+ sale=self.record,
+ product=self.gift_card.product,
+ quantity=1,
+ unit=self.gift_card.product.default_uom,
+ unit_list_price=self.gift_card.amount,
+ unit_gross_price=self.gift_card.amount,
+ gift_card_email=self.gift_card.email,
+ )
+
+
+class POSPayGiftCard(ModelView):
+ "POS Pay - Gift Card"
+ __name__ = 'sale.point.sale.pay.gift_card'
+
+ sale = fields.Many2One('sale.point.sale', "Sale")
+ product = fields.Many2One(
+ 'product.product', "Product", required=True,
+ domain=[
+ ('salable', '=', True),
+ ('gift_card', '=', True),
+ ])
+ amount = Monetary(
+ "Amount", currency='currency', digits='currency', required=True)
+ email = fields.Char("Email")
+
+ currency = fields.Function(
+ fields.Many2One('currency.currency', "Currency"),
+ 'on_change_with_currency')
+
+ @fields.depends('sale')
+ def on_change_with_currency(self, name=None):
+ if self.sale and self.sale.company:
+ return self.sale.company.currency.id
diff -r 58aa1f26ab0f -r db7d7f741246 sale.xml
--- a/sale.xml Sun Sep 26 23:11:21 2021 +0200
+++ b/sale.xml Mon Oct 11 23:55:17 2021 +0200
@@ -124,5 +124,46 @@
<field name="inherit" ref="sale.sale_line_view_form"/>
<field name="name">sale_line_form</field>
</record>
+
+ <record model="ir.action.report" id="report_gift_card">
+ <field name="name">Gift Cards</field>
+ <field name="report_name">sale.gift_card</field>
+ <field name="report">sale_gift_card/gift_card.fodt</field>
+ </record>
+ <record model="ir.action.keyword"
id="report_gift_card_keyword_gift_card">
+ <field name="keyword">form_print</field>
+ <field name="model">sale.gift_card,-1</field>
+ <field name="action" ref="report_gift_card"/>
+ </record>
+ <record model="ir.action.keyword" id="report_gift_card_keyword_sale">
+ <field name="keyword">form_print</field>
+ <field name="model">sale.sale,-1</field>
+ <field name="action" ref="report_gift_card"/>
+ </record>
+ </data>
+ <data depends="sale_point">
+ <record model="ir.ui.view" id="sale_point_sale_view_form">
+ <field name="model">sale.point.sale</field>
+ <field name="inherit" ref="sale_point.sale_view_form"/>
+ <field name="name">sale_point_sale_form</field>
+ </record>
+
+ <record model="ir.ui.view" id="sale_point_sale_line_view_form">
+ <field name="model">sale.point.sale.line</field>
+ <field name="inherit" ref="sale_point.sale_line_view_form"/>
+ <field name="name">sale_point_sale_line_form</field>
+ </record>
+
+ <record model="ir.ui.view"
id="sale_point_sale_pay_gift_card_view_form">
+ <field name="model">sale.point.sale.pay.gift_card</field>
+ <field name="type">form</field>
+ <field name="name">sale_point_sale_pay_gift_card_form</field>
+ </record>
+
+ <record model="ir.action.keyword"
id="report_gift_card_keyword_sale_point">
+ <field name="keyword">form_print</field>
+ <field name="model">sale.point.sale,-1</field>
+ <field name="action" ref="report_gift_card"/>
+ </record>
</data>
</tryton>
diff -r 58aa1f26ab0f -r db7d7f741246 tests/scenario_sale_gift_card.rst
--- a/tests/scenario_sale_gift_card.rst Sun Sep 26 23:11:21 2021 +0200
+++ b/tests/scenario_sale_gift_card.rst Mon Oct 11 23:55:17 2021 +0200
@@ -6,7 +6,7 @@
>>> import re
>>> from decimal import Decimal
- >>> from proteus import Model
+ >>> from proteus import Model, Report
>>> from trytond.tests.tools import activate_modules
>>> from trytond.modules.company.tests.tools import (
... create_company, get_company)
@@ -146,6 +146,12 @@
>>> card.number in msg
True
+Print gift cards::
+
+ >>> gift_card_report = Report('sale.gift_card')
+ >>> bool(gift_card_report.execute([sale]))
+ True
+
Check invoice::
>>> invoice, = sale.invoices
diff -r 58aa1f26ab0f -r db7d7f741246 tests/scenario_sale_point_gift_card.rst
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/scenario_sale_point_gift_card.rst Mon Oct 11 23:55:17 2021 +0200
@@ -0,0 +1,223 @@
+=============================
+Sale Point Gift Card Scenario
+=============================
+
+Imports::
+
+ >>> from decimal import Decimal
+
+ >>> from proteus import Model, Wizard, Report
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import (
+ ... create_company, get_company)
+ >>> from trytond.modules.account.tests.tools import (
+ ... create_fiscalyear, create_chart, get_accounts)
+ >>> from trytond.modules.account_invoice.tests.tools import (
+ ... set_fiscalyear_invoice_sequences)
+
+Activate modules::
+
+ >>> config = activate_modules(['sale_gift_card', 'sale_point'])
+
+ >>> Account = Model.get('account.account')
+ >>> AccountConfig = Model.get('account.configuration')
+ >>> GiftCard = Model.get('sale.gift_card')
+ >>> Journal = Model.get('account.journal')
+ >>> Location = Model.get('stock.location')
+ >>> POS = Model.get('sale.point')
+ >>> PaymentMethod = Model.get('sale.point.payment.method')
+ >>> ProductCategory = Model.get('product.category')
+ >>> ProductTemplate = Model.get('product.template')
+ >>> ProductUoM = Model.get('product.uom')
+ >>> Sale = Model.get('sale.point.sale')
+ >>> SaleConfig = Model.get('sale.configuration')
+ >>> Sequence = Model.get('ir.sequence')
+ >>> SequenceStrict = Model.get('ir.sequence.strict')
+ >>> SequenceType = Model.get('ir.sequence.type')
+
+Create company::
+
+ >>> _ = create_company()
+ >>> company = get_company()
+
+Create fiscal year::
+
+ >>> fiscalyear = set_fiscalyear_invoice_sequences(
+ ... create_fiscalyear(company))
+ >>> fiscalyear.click('create_period')
+
+Create chart of accounts::
+
+ >>> _ = create_chart(company)
+ >>> accounts = get_accounts(company)
+
+Setup gift card accounting::
+
+ >>> gift_card_type, = accounts['payable'].type.duplicate(
+ ... {'gift_card': True})
+ >>> gift_card_revenue = Account(name="Gift Card")
+ >>> gift_card_revenue.type = gift_card_type
+ >>> gift_card_revenue.deferral = True
+ >>> gift_card_revenue.save()
+ >>> account_config = AccountConfig(1)
+ >>> account_config.gift_card_account_revenue = gift_card_revenue
+ >>> account_config.save()
+
+Set gift card sequence::
+
+ >>> sale_config = SaleConfig(1)
+ >>> gift_card_sequence = Sequence(name="Gift Card")
+ >>> gift_card_sequence.sequence_type, = SequenceType.find([
+ ... ('name', '=', "Gift Card"),
+ ... ])
+ >>> gift_card_sequence.type = 'hexadecimal timestamp'
+ >>> gift_card_sequence.save()
+ >>> sale_config.gift_card_sequence = gift_card_sequence
+ >>> sale_config.save()
+
+Create gift card product::
+
+ >>> unit, = ProductUoM.find([('name', '=', "Unit")])
+
+ >>> template = ProductTemplate()
+ >>> template.name = "Gift Card"
+ >>> template.type = 'service'
+ >>> template.default_uom = unit
+ >>> template.salable = True
+ >>> template.gift_card = True
+ >>> template.list_price = Decimal('50')
+ >>> template.save()
+ >>> gift_card_product, = template.products
+
+Create account category::
+
+ >>> account_category = ProductCategory(name="Account Category")
+ >>> account_category.accounting = True
+ >>> account_category.account_revenue = accounts['revenue']
+ >>> account_category.save()
+
+Create product::
+
+ >>> unit, = ProductUoM.find([('name', '=', 'Unit')])
+
+ >>> template = ProductTemplate()
+ >>> template.name = 'product'
+ >>> template.default_uom = unit
+ >>> template.type = 'goods'
+ >>> template.salable = True
+ >>> template.account_category = account_category
+ >>> template.gross_price = Decimal('50.0000')
+ >>> template.save()
+ >>> product, = template.products
+
+Get journal::
+
+ >>> journal_revenue, = Journal.find([('type', '=', 'revenue')], limit=1)
+
+Get stock locations::
+
+ >>> storage_loc, = Location.find([('code', '=', 'STO')])
+ >>> customer_loc, = Location.find([('code', '=', 'CUS')])
+
+Create POS::
+
+ >>> pos = POS(name="POS")
+ >>> pos.journal = journal_revenue
+ >>> pos.sequence = SequenceStrict(name="POS", company=pos.company)
+ >>> pos.sequence.sequence_type, = SequenceType.find(
+ ... [('name', '=', "POS")], limit=1)
+ >>> pos.sequence.save()
+ >>> pos.storage_location = storage_loc
+ >>> pos.customer_location = customer_loc
+ >>> pos.save()
+
+Create a payment method::
+
+ >>> payment_method = PaymentMethod(name="Cash")
+ >>> payment_method.account = accounts['cash']
+ >>> payment_method.save()
+
+Make a sale::
+
+ >>> sale = Sale(point=pos)
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 10
+ >>> sale.save()
+ >>> sale.total
+ Decimal('500.00')
+
+Overpay::
+
+ >>> payment = Wizard('sale.point.sale.pay', [sale])
+ >>> payment.form.method = payment_method
+ >>> payment.form.amount = Decimal('600.00')
+ >>> payment.execute('pay')
+
+ >>> payment.form.amount
+ Decimal('-100.00')
+
+Return change with a gift card::
+
+ >>> payment.execute('gift_card')
+ >>> payment.form.product = gift_card_product
+ >>> payment.form.amount
+ Decimal('100.00')
+ >>> payment.execute('add_gift_card')
+
+ >>> sale.state
+ 'done'
+
+Check gift card::
+
+ >>> gift_card, = GiftCard.find([])
+ >>> gift_card.value
+ Decimal('100.00')
+ >>> gift_card.currency == sale.currency
+ True
+
+Print gift card::
+
+ >>> gift_card_report = Report('sale.gift_card')
+ >>> bool(gift_card_report.execute([sale]))
+ True
+
+Post sale::
+
+ >>> sale.click('post')
+ >>> sale.state
+ 'posted'
+
+Make a second sale and pay with gift card::
+
+ >>> sale = Sale(point=pos)
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 5
+ >>> sale.gift_cards.append(GiftCard(gift_card.id))
+ >>> sale.save()
+ >>> sale.total
+ Decimal('150.00')
+
+Pay::
+
+ >>> payment = Wizard('sale.point.sale.pay', [sale])
+ >>> payment.form.method = payment_method
+ >>> payment.execute('pay')
+
+ >>> sale.state
+ 'done'
+ >>> sale.total
+ Decimal('150.00')
+
+Check gift card::
+
+ >>> gift_card.reload()
+ >>> gift_card.spent_on == sale
+ True
+
+Post sale::
+
+ >>> sale.click('post')
+ >>> sale.state
+ 'posted'
diff -r 58aa1f26ab0f -r db7d7f741246 tests/test_sale_gift_card.py
--- a/tests/test_sale_gift_card.py Sun Sep 26 23:11:21 2021 +0200
+++ b/tests/test_sale_gift_card.py Mon Oct 11 23:55:17 2021 +0200
@@ -16,6 +16,7 @@
class SaleGiftCardTestCase(CompanyTestMixin, ModuleTestCase):
'Test Sale Gift Card module'
module = 'sale_gift_card'
+ extras = ['sale_point']
def suite():
@@ -32,4 +33,9 @@
tearDown=doctest_teardown, encoding='utf-8',
checker=doctest_checker,
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_sale_point_gift_card.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
return suite
diff -r 58aa1f26ab0f -r db7d7f741246 tryton.cfg
--- a/tryton.cfg Sun Sep 26 23:11:21 2021 +0200
+++ b/tryton.cfg Mon Oct 11 23:55:17 2021 +0200
@@ -9,6 +9,8 @@
product
sale
stock
+extras_depend:
+ sale_point
xml:
account.xml
product.xml
diff -r 58aa1f26ab0f -r db7d7f741246 view/sale_point_sale_form.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/view/sale_point_sale_form.xml Mon Oct 11 23:55:17 2021 +0200
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
+this repository contains the full copyright notices and license terms. -->
+<data>
+ <xpath expr="//page[@id='sale']" position="after">
+ <page name="gift_cards">
+ <field name="gift_cards" colspan="4" widget="many2many"/>
+ </page>
+ </xpath>
+</data>
diff -r 58aa1f26ab0f -r db7d7f741246 view/sale_point_sale_line_form.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/view/sale_point_sale_line_form.xml Mon Oct 11 23:55:17 2021 +0200
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
+this repository contains the full copyright notices and license terms. -->
+<data>
+ <xpath expr="//page[@id='general']" position="after">
+ <page id="gift_cards" string="Gift Cards">
+ <label name="gift_card_email"/>
+ <field name="gift_card_email"/>
+
+ <label name="gift_cards" colspan="4"/>
+ </page>
+ </xpath>
+</data>
diff -r 58aa1f26ab0f -r db7d7f741246 view/sale_point_sale_pay_gift_card_form.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/view/sale_point_sale_pay_gift_card_form.xml Mon Oct 11 23:55:17
2021 +0200
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
+this repository contains the full copyright notices and license terms. -->
+<form>
+ <label name="product"/>
+ <field name="product"/>
+ <label name="amount"/>
+ <field name="amount"/>
+
+ <label name="email"/>
+ <field name="email"/>
+
+ <field name="sale" colspan="4" invisible="1"/>
+</form>